C# 自定义用户控件的DependencyProperty上的绑定未在更改时更新
我在自定义用户控件上进行数据绑定时遇到困难。我创建了一个示例项目来突出我的问题。我对WPF和MVVM都是全新的,所以请容忍我 我创建了一个使用数据绑定两种方式的简单视图。内置控件上的数据绑定工作正常。我的自定义控件不。。。我在控件的C# 自定义用户控件的DependencyProperty上的绑定未在更改时更新,c#,wpf,data-binding,user-controls,dependency-properties,C#,Wpf,Data Binding,User Controls,Dependency Properties,我在自定义用户控件上进行数据绑定时遇到困难。我创建了一个示例项目来突出我的问题。我对WPF和MVVM都是全新的,所以请容忍我 我创建了一个使用数据绑定两种方式的简单视图。内置控件上的数据绑定工作正常。我的自定义控件不。。。我在控件的属性changedcallback中放置了一个断点。它在启动时被击中一次,但再也不会被击中。同时,我绑定到相同值的标签正在愉快地倒计时 我错过了什么?我的示例项目如下: 主窗口: <Window x:Class="WpfMVVMApp.MainWindow"
属性changedcallback
中放置了一个断点。它在启动时被击中一次,但再也不会被击中。同时,我绑定到相同值的标签正在愉快地倒计时
我错过了什么?我的示例项目如下:
主窗口:
<Window x:Class="WpfMVVMApp.MainWindow"
xmlns:local="clr-namespace:WpfMVVMApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.DataContext>
<local:CountdownViewModel />
</Grid.DataContext>
<Label Name="custName" Content="{Binding Path=Countdown.ChargeTimeRemaining_Mins}" Height="45" VerticalAlignment="Top"></Label>
<local:UserControl1 MinutesRemaining="{Binding Path=Countdown.ChargeTimeRemaining_Mins}" Height="45"></local:UserControl1>
</Grid>
</Window>
ViewModel:
namespace WpfMVVMApp
{
public class CountdownViewModel
{
public CountdownModel Countdown { get; set; }
DispatcherTimer timer;
private const int maxMins = 360;
public CountdownViewModel()
{
Countdown = new CountdownModel { ChargeTimeRemaining_Mins = 60 };
// Setup timers
timer = new DispatcherTimer();
timer.Tick += new EventHandler(this.SystemChargeTimerService);
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
private void SystemChargeTimerService(object sender, EventArgs e)
{
//convert to minutes remaining
// DEMO CODE - TODO: Remove
this.Countdown.ChargeTimeRemaining_Mins -= 1;
}
}
}
以下是我的用户控件的XAML:
<UserControl x:Class="WpfMVVMApp.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Name="Readout"></Label>
</Grid>
</UserControl>
namespace WpfMVVMApp
{
public partial class UserControl1 : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty MinutesRemainingProperty =
DependencyProperty.Register
(
"MinutesRemaining", typeof(int), typeof(UserControl1),
new UIPropertyMetadata(10, new PropertyChangedCallback(minutesRemainChangedCallBack))
);
#endregion
public int MinutesRemaining
{
get
{
return (int)GetValue(MinutesRemainingProperty);
}
set
{
SetValue(MinutesRemainingProperty, value);
}
}
static void minutesRemainChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args)
{
UserControl1 _readout = (UserControl1)property;
_readout.MinutesRemaining = (int)args.NewValue;
_readout.Readout.Content = _readout.MinutesRemaining;
}
public UserControl1()
{
InitializeComponent();
}
}
}
您的更改回调正在破坏绑定 作为一个框架:在您的窗口中有
UC.X=“{Binding a}”
,然后在该属性更改(在UC中)中有X=B代码>。这会破坏绑定,因为在这两种情况下都设置了X
要更正,请删除更改回调并将其添加到标签:
Content="{Binding MinutesRemaining, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
我试着让你的代码工作得很好。我所做的唯一更改是删除你拥有的propertychangedcallback背后的代码,并将标签(读数)数据绑定到dependency属性
用户控制(XAML)
<UserControl x:Class="WpfApplication1.UserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Name="Readout" Content="{Binding RelativeSource={RelativeSource
AncestorType=UserControl}, Path=MinutesRemaining}"/>
</Grid>
</UserControl>
谢谢你的回复。以前的绑定确实有效。但是,我创建dependency属性的原因是,我想做的不仅仅是在实际程序中设置标签(这只是一个简单的示例)。现在我看到,我正在为更改回调中剩余的分钟分配一个值,这打破了原始绑定。我把那行注释掉了,现在它可以像我预期的那样工作了。
<UserControl x:Class="WpfApplication1.UserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Name="Readout" Content="{Binding RelativeSource={RelativeSource
AncestorType=UserControl}, Path=MinutesRemaining}"/>
</Grid>
</UserControl>
public partial class UserControl1 : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty MinutesRemainingProperty =
DependencyProperty.Register
(
"MinutesRemaining", typeof(int), typeof(UserControl1),
new UIPropertyMetadata(10)
);
#endregion
public int MinutesRemaining
{
get
{
return (int)GetValue(MinutesRemainingProperty);
}
set
{
SetValue(MinutesRemainingProperty, value);
}
}
public UserControl1()
{
InitializeComponent();
}
}