我正在使用滑块实现用户可调整的Effect
,滑块旁边有一个重置按钮。我们的想法是允许用户重置回元数据中指定的Effect
属性的默认值。
我认为在XAML中这样做可能是微不足道的。
答案 0 :(得分:4)
依赖项属性实际上没有默认值。如果依赖项属性没有本地值,它将通过值继承或强制获取其值,具体取决于属性的实现方式。
你无法真正摆脱XAML中属性的本地值 - 这需要你在属性上调用ClearValue
,并且无法找到对象并以声明方式调用它上面的方法。但只要属性通过值继承(而不是值强制)获得其值 - 您可以通过将属性绑定到它从相应祖先继承的属性来实现基本相同的事情
例如,这是您用来创建ListBox
的样式,用于设置未选中的所有项目的前景色:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter
Property="Foreground"
Value="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox},
Path=Foreground}" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
这基本上通过绑定显式实现了值继承。它确实意味着ListBoxItem.Foreground
属性现在具有本地值,并且无论何时更改Foreground
的{{1}}属性,它的绑定都会更新ListBox
1}}而不是依赖属性系统。如果您的ListBoxItem.Foreground
中有数十万件物品,这实际上很重要。但在大多数现实案例中,你永远不会注意到差异。
答案 1 :(得分:1)
为了避免逻辑周期, WPF 强烈抵制将DependencyProperty
值设置为其当前值的尝试。这是初始化期间的一个问题,您希望根据元数据中记录的DefaultValue
触发相关逻辑,以便首次设置的所有内容依赖属性。 WPF不会这样做,因为作为一种特殊情况,所有这些属性都已经获得了它们的默认值而没有执行任何这样的逻辑。
据我所知,InvalidateProperty
,CoerceValue
或ClearValue
的任何组合都不会说服WPF完成这项工作。一个微不足道的修复方法是以某种方式召唤一个希望无害的非默认值来将其更改为,然后通过ClearValue
重置该值。然而,这看起来很糟糕,因为确定“无害”价值可能不切实际。也许更糟糕的是,这种方法会不必要地两次骚扰依赖图,而不是仅仅一次。
作为一个更优雅的解决方案,您可以在每个相关对象的构造函数中调用以下扩展方法,以手动调用需要传播其更改的每个PropertyChanged
的{{1}}逻辑。该助手将根据存储在相应元数据中的默认值触发后续更改。
DependencyProperty
如图所示,该函数包括检查public static void ResetValue(this DependencyObject _this, DependencyProperty dp)
{
var md = dp.GetMetadata(_this.GetType());
if (_this.GetValue(dp).Equals(md.DefaultValue))
{
var args = new DependencyPropertyChangedEventArgs(dp, DependencyProperty.UnsetValue, md.DefaultValue);
md.PropertyChangedCallback(_this, args);
}
else
_this.ClearValue(dp);
}
实际上是否有效,因此除了初始化方案之外,您还可以使用此函数替代ClearValue
。为了清楚地演示,此方法不验证宿主对象实际上暴露了任何属性更改逻辑,但这将是一个简单的更改。例如,在C#7中:
ClearValue
班级中的用法示例:
// ...
md.PropertyChangedCallback?.Invoke(_this, args);