当我在运行时设置IsClosed
的值时,OnIsClosedChanged()
被称为罚款。
但是,Designer会设置属性的值,但不会调用OnIsClosedChanged()
。
public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
public bool IsClosed {
get {
return (bool)this.GetValue(IsClosedProperty);
}
set {
if ((bool)this.GetValue(IsClosedProperty) == value)
return;
this.SetValue(IsClosedProperty, value);
OnIsClosedChanged();
}
}
private void OnIsClosedChanged() {
_rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star);
}
显然,IsClosed
未被Designer修改,只有IsClosedProperty
才会收到xaml更改。
我的问题是:如何在Designer中修改值后运行IsClosed
。或者至少为非运行时更改添加一些逻辑。
答案 0 :(得分:8)
您必须使用属性元数据注册PropertyChangedCallback。
原因是在XAML中设置的依赖项属性或绑定或某些其他源不会调用CLR包装器(setter方法)。原因在MSDN上的XAML Loading and Dependency Properties文章中进行了解释:
出于实施原因,它在计算上更便宜 将属性标识为依赖属性并访问该属性 系统SetValue方法设置它,而不是使用属性 包装器和它的二传手。
...
因为当前的WPF实现了XAML处理器的行为 对于属性设置完全绕过包装器,你不应该 将任何其他逻辑放入包装器的set定义中 您的自定义依赖属性。如果你把这样的逻辑放在集合中 定义,然后在属性时不执行逻辑 在XAML而不是代码中设置。
您的代码应如下所示:
public static readonly DependencyProperty IsClosedProperty =
DependencyProperty.Register(
"IsClosed", typeof(bool), typeof(GroupBox),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.AffectsRender,
(o, e) => ((GroupBox)o).OnIsClosedChanged()));
public bool IsClosed
{
get { return (bool)GetValue(IsClosedProperty); }
set { SetValue(IsClosedProperty, value); }
}
private void OnIsClosedChanged()
{
_rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star);
}
答案 1 :(得分:1)
现在自己找到答案。 ValidateValueCallback非常接近! (正如Alex K所指出的那样)但它是一种静态方法,我没有得到任何已经改变的实例的引用。关键是在FrameworkPropertyMetadata中使用PropertyChangedCallback,它也是传递给Property.Register方法的参数。
参见:
public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnIsClosedChangedPCC)));
public bool IsClosed {
get {
return (bool)this.GetValue(IsClosedProperty);
}
set {
this.SetValue(IsClosedProperty, value);
OnIsClosedChanged();
}
}
private static void OnIsClosedChangedPCC(DependencyObject d, DependencyPropertyChangedEventArgs e) {
GroupBox current = (GroupBox)d;
current.IsClosed = current.IsClosed;
}
private void OnIsClosedChanged() {
_rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star);
}
现在重新设置触发IsClosedValue
OnIsClosedChanged
的{{1}}
感谢您的帮助!