如何在DependencyProperty中传播PropertyChanged更改
我有一个实现INotifyPropertyChanged的类。 该类的一个实例在窗口中声明为DependencyProperty,例如,
public IMyClass MyClass
{
get { return (IMyClass)GetValue(MyClassProperty); }
set { SetValue(MyClassProperty, value); }
}
public static readonly DependencyProperty MyClassProperty=
DependencyProperty.Register("MyClass", typeof(IMyClass), typeof(MainWindow), new UIPropertyMetadata(null));
在XAML中,我有一个绑定到这个类的元素
Text="{Binding MyClass, Converter={StaticResource someConverter}}
无论何时我在MyClass中更改属性,我都希望触发某个转换器。 但是,只有当我完全更换MyClass时才会发生这种情况。 有没有办法将DependencyProperty更新绑定到我的MyClass PropertyChanged?
更新。 本着AresAvatar解决方案的精神,这里是我们迄今为止的。 剩下的问题是如何调用InvalidateProperty(没有MyClass跟踪它...)
public IMyClass MyClass
{
get { return (IMyClass)GetValue(MyClassProperty); }
set { SetValue(MyClassProperty, value); }
}
public static readonly DependencyProperty MyClassProperty =
DependencyProperty.Register("MyClass", typeof(IMyClass), typeof(MainWindow),
new UIPropertyMetadata(null, new PropertyChangedCallback(OnMyClassChanged)));
private static void OnMyClassChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
{
((IMyClass)e.OldValue).PropertyChanged -= ((MainWindow)d).MyClass_PropertyChanged;
}
if (e.NewValue != null)
{
((IMyClass)e.NewValue).PropertyChanged += ((MainWindow)d).MyClass_PropertyChanged;
}
}
private void MyClass_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
this.InvalidateProperty(MyClassProperty); <----- still does not refresh binding, but called.
}
转换器不应该做比简单转换更多的工作,你的问题听起来像转换器使用对象的很多属性来创建一些组合的值。 使用MultiBinding
来代替所需的对象的所有不同属性,这样MultiBinding
上的MultiValueConverter
将在任何这些属性更改时触发。
此外,由于您似乎创建了文本,因此您可能无需使用任何转换器即可离开,因为StringFormat
可能就足够了。
在MyClass中,实现一个NotifyPropertyChanged事件。 然后添加一个属性更改回调到您的MyClass DependencyProperty。 在DP的属性已更改回调中,将新的MyClass NotifyPropertyChanged事件挂接到第二个回调函数(并使用 - =运算符取消以前的值(如果有的话))。 在第二个回调函数中,调用DependencyObject.InvalidateProperty,以便更新绑定。
编辑:你可能需要触发一个绑定更新:
BindingExpressionBase exp = BindingOperations.GetBindingExpressionBase(this, Container.MyClassProperty);
if (exp != null)
exp.UpdateTarget();
class MyClass : INotifyPropertyChanged
{
/// <summary>
/// Event raised when a property is changed
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the property changed event
/// </summary>
/// <param name="e">The arguments to pass</param>
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
/// <summary>
/// Notify for property changed
/// </summary>
/// <param name="name">Property name</param>
protected void NotifyPropertyChanged(string name)
{
OnPropertyChanged(new PropertyChangedEventArgs(name));
}
/// <summary>
/// The parent container object
/// </summary>
public Container Parent { get; set; }
// Some data
int x;
}
class Container : DependencyObject
{
public static readonly DependencyProperty MyClassProperty = DependencyProperty.Register("MyClass", typeof(MyClass), typeof(Container), new FrameworkPropertyMetadata(MyClassPropChanged));
public MyClass MyClass
{
get { return (MyClass)GetValue(MyClassProperty); }
set { SetValue(MyClassProperty, value); }
}
void MyClassPropChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Container ct = d as Container;
if (ct == null)
return;
MyClass oldc = e.OldValue as MyClass;
if (oldc != null)
{
oldc.PropertyChanged -= new PropertyChangedEventHandler(MyClass_PropertyChanged);
oldc.Parent = null;
}
MyClass newc = e.NewValue as MyClass;
if (newc != null)
{
newc.Parent = ct;
newc.PropertyChanged += new PropertyChangedEventHandler(MyClass_PropertyChanged);
}
}
void MyClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MyClass mc = sender as MyClass;
if (mc == null || mc.Parent == null)
return;
mc.Parent.InvalidateProperty(Container.MyClassProperty);
}
}
我发现的唯一技巧是在战略上放置的事件处理程序(如LostFocus)中调用绑定的UpdateSource方法。
private void mycontrol_LostFocus(object sender, RoutedEventArgs e)
{
if (mycontrol.IsModified)
{
var binding = mycontrol.GetBindingExpression(MyControl.FooBarProperty);
binding.UpdateSource();
}
}
如果你不关心琐事,或者如果你的控件不需要输入焦点,你可以在mycontrol_PropertyChanged事件或类似事件中执行此操作。 但是,强制每个属性更改或每次按键的转换周期都可能会影响验证。
链接地址: http://www.djcxy.com/p/67573.html上一篇: How to propagate PropertyChanged changes in DependencyProperty
下一篇: How to bind to the sum of two data bound values in WPF?