如何在XAML中阻止属性值从元素树向下流动?

3
假设我有一个已被禁用的控件。它包含许多元素,但我希望其中一个子元素保持启用状态。
类似这样:
<ContentControl IsEnabled="False">
    <Border>
        <Button Content="Button" IsEnabled="True"/>
    </Border>
</ContentControl>

在这个例子中,按钮的IsEnabled="True"设置被其父级覆盖了。有没有办法阻止这种情况发生?
这似乎是一件奇怪的事情,但我遇到了这样的情况:当控件被禁用且用户在其中点击鼠标时,我仍希望触发某个事件。
我在WPF Unleashed中读到,将某个内容放进Frame控件中,“隔离了该内容与UI的其他部分,并且通常会继承下来的属性会在Frame中停止”,但是在上面的示例中将按钮放在一个Frame中并不起作用。
我是不是走错了路?
2个回答

4
如果您可以继承按钮(或任何您需要的控件),您可以替换CoerceValue以避免此行为(实际上,我认为IsEnabled应该像IsChecked一样工作,是一个bool?其中null表示使用父值,任何特定值都应保留...但由于这不是行为,使用此解决方案将解决问题):
public sealed class InheritedButton:
  Button
{
  static InheritedButton()
  {
    InheritedButton.IsEnabledProperty.OverrideMetadata
    (
      typeof(InheritedButton),
      new FrameworkPropertyMetadata
      (
        true,
        null,
        _CoerceIsEnabled
      )
    );
  }
  private static object _CoerceIsEnabled(DependencyObject source, object value)
  {
    return value;
  }
}

4

这不是继承,而是组合

包含控件被禁用,因此其中所有的控件都被禁用

启用容器和所需控件,并禁用其他控件


@Steven:谢谢。"那不是继承,那是组合"。仅出于兴趣,在《WPF Unleashed》中,Adam Nathan谈到了“属性值继承”,这是他用来指代属性值沿着元素树向下流动的术语。因此,似乎有“继承”这个术语,大多数/所有人用它来指代基于类的继承,Nathan的“属性值继承”,以及“组合”(据我所见,在MSDN上基本上是指UI布局?)。如果我错了,请纠正我。我正在努力掌握基础知识。 - user255594
1
@cfouche从未读过Nathan的文章,但我怀疑他在术语上有些不严谨。继承是语义上的:一个人是哺乳动物,自行车是交通工具。组合是包含和使用:口袋里的零钱,发动机内的火花塞。在这种情况下,包含控件就像一个盒子,如果它无法打开(被禁用),那么自然地,它内部的任何内容也无法打开。对于Visible属性也是同样的道理(启用/禁用是可见/不可见的一种较弱形式);如果容器不可见,则其内容必然也是不可见的。 - Steven A. Lowe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接