自定义用户控件的 DependencyProperty 绑定未在更改时更新
Posted
技术标签:
【中文标题】自定义用户控件的 DependencyProperty 绑定未在更改时更新【英文标题】:Binding on DependencyProperty of custom User Control not updating on change 【发布时间】:2013-05-04 12:36:15 【问题描述】:我在自定义用户控件上的数据绑定方面遇到困难。我创建了一个示例项目来突出我的问题。我对 WPF 和本质上的 MVVM 都是全新的,所以请耐心等待......
我创建了一个简单的视图,它以两种方式使用数据绑定。内置控件上的数据绑定工作得很好。我的自定义控件没有...我在我的控件的PropertyChangedCallback
中放置了一个断点。它在启动时被击中一次,但以后再也不会。同时,我绑定到相同值的标签正在愉快地倒计时。
我错过了什么?我的示例项目如下:
主窗口:
<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>
这是我的模型:
namespace WpfMVVMApp
public class CountdownModel : INotifyPropertyChanged
private int chargeTimeRemaining_Mins;
public int ChargeTimeRemaining_Mins
get
return chargeTimeRemaining_Mins;
set
chargeTimeRemaining_Mins = value;
OnPropertyChanged("ChargeTimeRemaining_Mins");
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
#endregion
视图模型:
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();
【问题讨论】:
【参考方案1】:您的更改回调正在破坏绑定。
作为一个骨架:在您的窗口中您有UC.X="Binding A"
,然后在该属性更改中(在 UC 中)您有X=B;
。这会破坏绑定,因为在这两种情况下您都设置了X
。
要纠正,删除更改回调并将其添加到标签:
Content="Binding MinutesRemaining, RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type UserControl"
【讨论】:
感谢您的回复。绑定确实有效。然而,我创建依赖属性的原因是因为我想做的不仅仅是在我的实际程序中设置一个标签(这只是一个简单的例子)。我现在看到我在更改回调中为 MinutesRemaining 分配了一个值,这破坏了原始绑定。我注释掉了那行,现在它可以按预期工作了。【参考方案2】:我试过你的代码工作正常,我所做的唯一更改是删除你拥有的 propertychangedcallback 后面的代码,并将标签(读出)数据绑定到依赖属性。
用户控制(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>
用户控制(代码隐藏)
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();
【讨论】:
以上是关于自定义用户控件的 DependencyProperty 绑定未在更改时更新的主要内容,如果未能解决你的问题,请参考以下文章