[英]How to fire Property Changed Event when it's not actually changing
so I have a model which contains 2 variables, a List and a DateTime. 所以我有一个模型,其中包含2个变量,一个List和一个DateTime。 In my UserControl I have a DependencyProperty and I also defined a PropertyChangedCallback. 在我的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
}
On my form there is a button, which do the changes on the other model variable (on the DateTime). 在我的表单上有一个按钮,用于对另一个模型变量(在DateTime上)进行更改。
private void Date_Click(object sender, RoutedEventArgs e)
{
MyModel model = DataContext as MyModel;
if (model != null)
{
model.Date = model.Date.AddDays(1);
}
}
And finally here is my model. 最后是我的模型。
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 declaration is the following. XAML声明如下。
<local:UC My="{Binding My}" />
So my problem is the after I hit the run, it fires the OnMyProperty once, after that if I hit the button, it changes the DateTime property well, but the OnMyProperty callback doesn't firing again. 所以我的问题是,在我点击运行后,它会触发一次OnMyProperty,然后如果我按下按钮,它将很好地更改DateTime属性,但是OnMyProperty回调不会再次触发。 However I noticed that if I modify my model like this 但是我注意到如果我像这样修改我的模型
public DateTime Date
{
get
{
return _Date;
}
set
{
_Date = value;
_My = new List<MyContainer>(_My); //added
OnPropertyChanged("Date");
OnPropertyChanged("My");
}
}
now it fires it every time when I hit the button. 现在每次按下按钮时都会触发它。 How can I trigger the second behaviour without that modification? 如果不进行修改,如何触发第二种行为?
After setting the value of a DependencyProperty
it first checks if the new value is different to the old one. 设置DependencyProperty
的值后,它首先检查新值是否与旧值不同。 Only in this case the PropertyChangedCallback
method you registered with that DependencyProperty
is called. 仅在这种情况下,才调用您在该DependencyProperty
注册的PropertyChangedCallback
方法。 So the name Property Changed makes sense. 因此,名称Property Changed很有意义。
In your (not modified) case you not even try to change My
(only Date
). 在您(未修改)的情况下,您甚至都不会尝试更改My
(仅Date
)。 So there is no reason to raise the callback function. 因此,没有理由提高回调函数。
The answer is that you almost certainly do not need to do this. 答案是您几乎肯定不需要这样做。 When you ask a question about how to make the framework do something it really does not want to do, always say why you think you need to do that . 当您询问有关如何使框架执行其确实不希望执行的操作的问题时,请始终说出为什么您认为需要执行此操作 。 It's very likely that there's a much easier answer that everybody else is already using. 很有可能其他人已经在使用一个更简单的答案。
The only thing you have bound to the control is My
. 您绑定到控件的唯一东西是My
。 Therefore, if My
hasn't changed, then the state of the control should not change. 因此,如果My
尚未更改,则控件的状态不应更改。 If you want the state of the control to change when Date
changes, bind Date
to some property of the control. 如果你想控制的状态改变时, Date
的变化,结合Date
到控制的某些属性。 The only way the control should ever get information from any viewmodel is through binding one of its dependency properties to a property of the viewmodel. 控件应该从任何视图模型获取信息的唯一方法是将其依赖项属性之一绑定到视图模型的属性。
The control should not ever know or care who or what is providing values for its properties. 该控件永远不应该知道或关心谁或什么为其属性提供值。 It should be able to do its job knowing only the property values it has been given. 它仅应知道已赋予的属性值就能够执行其工作。
If the contents of My
have changed -- you added an item or removed one -- of course the control has no way of knowing that, because you refused to tell it. 如果My
的内容已更改-您添加了一个项目或删除了一个项目-则控件无法知道这一点,因为您拒绝告诉它。 You're just telling it there's a new list. 您只是在告诉它有一个新列表。 It checks, sees it's still got the same old list, and ignores you. 它检查,发现它仍然有相同的旧列表,并忽略了您。 The My
property of your viewmodel should be an ObservableCollection
, because that will notify the control when you add or remove items in the collection. 您的viewmodel的My
属性应该是ObservableCollection
,因为当您添加或删除集合中的项目时,它将通知控件。
The items themselves, your MyContainer
class, must implement INofityPropertyChanged
as well, if you want to be able to change their properties while they are displayed in the UI. 如果您想要在UI中显示项目时更改其属性,则项目本身(您的MyContainer
类)也必须实现INofityPropertyChanged
。
The dependency property My
on your control must not be of type List<T>
. 您控件上的依赖项属性My
的类型不能为List<T>
。 It should probably be type object
, just like ItemsControl.ItemsSource
. 它可能应该是object
类型,就像ItemsControl.ItemsSource
一样。 Then your control template can display it in an ItemsControl
which knows what to do with it. 然后,您的控件模板可以在知道如何使用它的ItemsControl
显示它。 If an ObservableCollection
is bound to it as I suggested above, the ItemsControl
will update automatically. 如果如上所述将ObservableCollection
绑定到它,则ItemsControl
将自动更新。 In OnMyProperty
, your control class can check to see if it's an observable collection as well: 在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.
};
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.