所以我有一个包含2个变量的模型,一个List和一个DateTime。在我的UserControl中,我有一个DependencyProperty,我还定义了一个PropertyChangedCallback。
public static readonly DependencyProperty MyProperty = DependencyProperty.Register("My", typeof(List<MyContainer>), typeof(UC), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnMyProperty)));
public List<MyContainer> My
{
get
{
return GetValue(MyProperty) as List<MyContainer>;
}
set
{
SetValue(MyProperty, value);
}
}
private static void OnMyProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UC control = d as UC;
//do stuff
}
在我的表单上有一个按钮,可以对其他模型变量进行更改(在DateTime上)。
private void Date_Click(object sender, RoutedEventArgs e)
{
MyModel model = DataContext as MyModel;
if (model != null)
{
model.Date = model.Date.AddDays(1);
}
}
最后这是我的模特。
public class MyModel : INotifyPropertyChanged
{
private List<MyContainer> _My;
private DateTime _Date;
public MyModel()
{
_Date = DateTime.Now.Date;
_My = new List<MyContainer>();
}
public List<MyContainer> My
{
get
{
return _My;
}
set
{
_My = value;
OnPropertyChanged("My");
}
}
public DateTime Date
{
get
{
return _Date;
}
set
{
_Date = value;
OnPropertyChanged("Date");
OnPropertyChanged("My");
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
XAML声明如下。
<local:UC My="{Binding My}" />
所以我的问题是在我点击运行之后,它会触发OnMyProperty一次,之后如果我点击按钮,它会很好地改变DateTime属性,但是OnMyProperty回调不会再次触发。但是我注意到如果我像这样修改我的模型
public DateTime Date
{
get
{
return _Date;
}
set
{
_Date = value;
_My = new List<MyContainer>(_My); //added
OnPropertyChanged("Date");
OnPropertyChanged("My");
}
}
现在每次按下按钮时它都会触发它。如何在没有修改的情况下触发第二种行为?
答案 0 :(得分:1)
设置DependencyProperty
的值后,首先检查新值是否与旧值不同。只有在这种情况下才会调用您在PropertyChangedCallback
注册的DependencyProperty
方法。所以名称Property Changed 是有道理的。
在您的(未修改)案例中,您甚至不尝试更改My
(仅Date
)。所以没有理由提出回调函数。
答案 1 :(得分:0)
答案是你几乎肯定不需要这样做。当你提出一个关于如何让框架做一些它真的不想做的事情的问题时,总是说为什么你认为你需要这样做。这很可能是其他人已经在使用的答案。
你唯一能控制的是My
。因此,如果My
未更改,则控件的状态不应更改。如果希望在Date
更改时更改控件的状态,请将Date
绑定到控件的某个属性。控件应该从任何viewmodel获取信息的 only 方式是通过将其依赖属性之一绑定到viewmodel的属性。
控件不应该知道或关心谁或什么为其属性提供价值。它应该能够只知道它给出的属性值来完成它的工作。
如果My
的内容发生了变化 - 你添加了一个项目或删除了一个项目 - 当然控制无法知道这一点,因为你拒绝告诉它。你只是告诉它有一个新的清单。它检查,看到它仍然有相同的旧列表,并忽略你。您的viewmodel的My
属性应该是ObservableCollection
,因为这会在您添加或删除集合中的项目时通知控件。
项目本身,即MyContainer
类,如果您希望能够在UI中显示属性时更改其属性,则必须实现INofityPropertyChanged
。
控件上的依赖项属性My
不得为List<T>
类型。它应该是object
类型,就像ItemsControl.ItemsSource
一样。然后,您的控件模板可以在ItemsControl
中显示它,它知道如何处理它。如果我按照上面的建议绑定了ObservableCollection
,则ItemsControl
会自动更新。在OnMyProperty
中,您的控件类可以检查它是否也是一个可观察的集合:
private static void OnMyProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UC control = d as UC;
if (e.NewValue is INotifyCollectionChanged)
{
(e.NewValue as INotifyCollectionChanged).CollectionChanged +=
(s, ecc) => {
// Do stuff with UC and ecc.NewItems, ecc.OldItems, etc.
};
}
}