WPF的PropertyChange不级联 - 动画一个自定义类的DependencyProperty改变其他属性 - 的PropertyChange只为第一火灾
-
12-09-2019 - |
题
非常简化的,这是我的问题:(在底部溶液)
我有一个自定义类,继承设置动画和INotifyPropertyChange,含有一个的DependencyProperty(我动画,说从1到10)和一个额外的属性(我想从XAML与使用的结合):
MyClass : Animatable, INotifyPropertyChanged {
public static DependencyProperty AnimateValueProperty = DependencyProperty.Register(
"AnimateValue",
typeof(double),
typeof(MyClass)
);
public double AnimateValue {
get { return (double)GetValue(AnimateValueProperty); }
set {
SetValue(AnimateValueProperty, value);
OnPropertyChanged(new PropertyChangedEventArgs("AnimateValue"));
OnPropertyChanged(new PropertyChangedEventArgs("GuiValue")); //Added in edit
}
}
}
public double GuiValue {
get {
return AnimateValue + 10;
//More fancy stuff happening in the real class...
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
if (PropertyChanged != null) {
PropertyChanged(this, e);
}
}
protected override Freezable CreateInstanceCore() {
return new MyClass();
}
}
当我绑定的GUI元素我其实动画属性(AnimateValue)一切正常 - 当我的GUI元素绑定到相关的属性(GuiValue)没有任何反应。我想这改变的事件没有达到这个属性,但我真的不知道该如何解决这个问题。任何指针?
任何帮助是非常感谢!
编辑:谢谢你从亚当·西尔斯和王凯两个答复,我愚蠢的离开了第二OnPropertyChange电话,但我已尝试之前,它没有工作。为了调试,我把的WriteLine在AnimateValue.set功能看哪! - 它并不会在所有执行
我也试图改变getter方法总是返回20 - 没有任何变化! :-o好像动画完全跳过属性的get和set和动画,并读取底层的DependencyProperty ......还是我误会了?我用动画的代码是:
DoubleAnimation da = new DoubleAnimation (1, 10, new Duration(TimeSpan.FromSeconds(3)));
myClassInstance.BeginAnimation(MyClass.AnimateValueProperty, da);
嗯......这里编写代码后似乎很合理的设置器不使用(虽然我真的很喜欢它的!) - 但尽管如此,基本的问题,代表,我仍然不明白为什么吸气剂不使用!
EDIT2:<!强> 解决方案 强>
如所建议的下面我不可能使用INotifyPropertyChange用于连接到的DependencyProperty属性 - 动画和XAML使用DepencencyProperty内部和完全不使用getter和setter。
因此 - PropertyChangedCallback到变化通知他人,CoerceValueCallback“修理”的数据。也可以验证数据,所有这一切都是在构造的DependencyProperty完成。谢谢大家!
谢谢!
/维克多
解决方案
这里是用于与依赖属性使用属性更改notifaction图案
public Boolean PasswordBoxVisible {
get { return (Boolean)GetValue(PasswordBoxVisibleProperty); }
set { SetValue(PasswordBoxVisibleProperty, value); }
}
public static readonly DependencyProperty PasswordBoxVisibleProperty =
DependencyProperty.Register("PasswordBoxVisible", typeof(Boolean), typeof(UserControl), new UIPropertyMetadata(false, new PropertyChangedCallback(PropChanged)));
//this method is called when the dp is changed
static void PropChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
UserControl userControl = o as UserControl;
//now you can use this to call some methods, raise other value changed etc, in this case OtherProperty.
userControl.NotifyPropertyChanged("OtherProperty");
}
我有一种感觉,但我不能完全肯定,那你可能需要做的是迫使其他值。 看看这篇文章 在裹胁值回调部p>
其他提示
通过设定AnimateValue的值,你告诉WPF它已经改变了。但你永远不会告知GuiValue已经改变了WPF。 WPF的数据绑定框架应该是怎样知道GuiValue当你不知道它有什么改变?
当你更新AnimateValue,提高变更的通知(其本身是没有必要的,因为它是一个依赖属性),你也需要筹集约GuiValue通知,是因为它是依赖于AnimateValue但手动计算内属性。
基本上只是添加
OnPropertyChanged(new PropertyChangedEventArgs("GuiValue"));
到AnimateValue设定的块。
<强>更新强>
根据新修改,如果做你的财产通过XAML中,吸气设定/依赖项属性的setter方法不会被调用,这一切都是通过做的GetValue /直接的SetValue
如果您需要响应局部地变化,重写OnPropertyChanged或提供内部DependencyProperty.Register变化回调
我不知道如果我明白你的意思。但是,看看是否有所帮助。
public double AnimateValue {
get { return (double)GetValue(AnimateValueProperty); }
set {
SetValue(AnimateValueProperty, value);
OnPropertyChanged(new PropertyChangedEventArgs("AnimateValue"));
OnPropertyChanged(new PropertyChangedEventArgs("GuiValue "));
}
}
}
如果你的对象是从依赖对象派生那么你可以不使用INotifyPropertyChanged的,因为绑定体系结构将只使用依赖项属性Resgistration才能使用绑定。
有关这一点,你需要的只读依赖项属性我已经解释如下。
public static DependencyProperty AnimateValueProperty =
DependencyProperty.Register(
"AnimateValue",
typeof(double),
typeof(MyClass)
);
// This is for the Readonly GuiValueKey property
public static DependencyPropertyKey GuiValueKey =
DependencyProperty.RegisterReadOnly (
"GuiValue",
typeof(double),
typeof(MyClass),
new UIPropertyMetadata(0.0)
);
public double AnimateValue {
get { return (double)GetValue(AnimateValueProperty); }
set {
SetValue(AnimateValueProperty, value);
// Following statement update GuiValue wherever it
// is binded
this.SetValue(GuiValueKey,value + 10);
}
}
}
// you dont even need following line...
// but its good to have it..
public double GuiValue {
get {
return (double)this.GetValue(GuiValueKey);
}
}