当父控件被禁用时启用子控件

8

我有一个包含超链接的按钮,如下:

<Button IsEnabled="False">
    <Hyperlink IsEnabled="True">Testing</Hyperlink>
</Button>

我希望链接可以启用,但按钮必须禁用。我该如何实现这一点?

上述方法只会导致两个控件都被禁用。


在按钮内部放置超链接的目的是什么? - Abdusalam Ben Haj
@AbZy 超链接显示了按钮中其他内容的元信息(为了简洁起见,我已省略)。即使按钮本身被禁用,我仍希望用户能够访问那些元信息。 - Justin
2个回答

3
我通过创建一个简单的包装元素来解决这个问题,打破了从父元素继承的“IsEnabled”链。
框架的默认强制回调会检查父级“IsEnabled”值并继承它。该控件设置了一个新的强制回调,只是直接返回值而不检查继承。
public class ResetIsEnabled : ContentControl
{
    static ResetIsEnabled()
    {
        IsEnabledProperty.OverrideMetadata(
            typeof(ResetIsEnabled),
            new UIPropertyMetadata(
                defaultValue: true,
                propertyChangedCallback: (_, __) => { },
                coerceValueCallback: (_, x) => x));
    }
}

在问题的示例中,它将被用作以下方式:
<Button IsEnabled="False">
  <ResetIsEnabled>
    <!-- Child elements within ResetIsEnabled have IsEnabled set to true (the default value) -->
    <Hyperlink>Testing</Hyperlink>
  </ResetIsEnabled>
</Button>

1
简单而有效的解决方案! - theartwebreathe

0

控件Hyperlink的属性IsEnabled有些奇怪。除了您提到的从父控件继承完整值之外,还有另外一种类似的情况。

对于特定控件的Hyperlink,如果已被关闭(IsEnabled="False"),设置 (IsEnabled="True") 将不会更新Hyperlink属性。解决方案是为Hyperlink使用相对源(更多信息)。

针对您的问题,我决定采用非标准的解决方式。因此我创建了一个具有自己依赖属性的Class。它有一个属性MyIsEnabledMyStyle。正如您从标题中猜到的那样,第一个设置了其属性IsEnabled,而MyStyle需要指定按钮样式,模拟IsEnabled="False"的行为。

模拟禁用样式

<Style x:Key="SimulateDisable" TargetType="{x:Type Button}">
    <Setter Property="Opacity" Value="0.5" />
    <Setter Property="Background" Value="Gainsboro" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border CornerRadius="4" BorderThickness="1" BorderBrush="DarkBlue" SnapsToDevicePixels="True">
                    <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

定义具有自己属性的按钮

<Button Name="MyButton" local:MyClass.MyIsEnabled="False" local:MyClass.MyStyle="{StaticResource SimulateDisable}" Width="100" Height="30" Click="Button_Click">
    <Hyperlink IsEnabled="True" Click="Hyperlink_Click">Testing</Hyperlink>
</Button>      

MyClass 的清单

public class MyClass : DependencyObject
{
    public static readonly DependencyProperty MyIsEnabledProperty;

    public static readonly DependencyProperty MyStyleProperty;

    #region MyIsEnabled

    public static void SetMyIsEnabled(DependencyObject DepObject, bool value)
    {
        DepObject.SetValue(MyIsEnabledProperty, value);
    }

    public static bool GetMyIsEnabled(DependencyObject DepObject)
    {
        return (bool)DepObject.GetValue(MyIsEnabledProperty);
    }

    #endregion MyIsEnabled

    #region MyStyle

    public static void SetMyStyle(DependencyObject DepObject, Style value)
    {
        DepObject.SetValue(MyStyleProperty, value);
    }

    public static Style GetMyStyle(DependencyObject DepObject)
    {
        return (Style)DepObject.GetValue(MyStyleProperty);
    }

    #endregion MyStyle

    static MyClass()
    {
        MyIsEnabledProperty = DependencyProperty.RegisterAttached("MyIsEnabled",
                              typeof(bool),
                              typeof(MyClass),
                              new UIPropertyMetadata(false, OnPropertyChanged));

        MyStyleProperty = DependencyProperty.RegisterAttached("MyStyle",
                          typeof(Style),
                          typeof(MyClass),
                          new UIPropertyMetadata(OnPropertyChanged));
    }

    private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        Button MyButton = sender as Button;
        bool MyBool = GetMyIsEnabled(MyButton);

        if (MyBool == false)
        {
            MyButton.Style = MyClass.GetMyStyle(MyButton);
        }            
    }
}

为了事件Hyperlink,返回e.Handled = true,以使下一个事件不会发生。

private void Hyperlink_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hyperlink Click!");

    e.Handled = true;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Button Click! Don't show it's!");
}      

输出

enter image description here

附言:抱歉晚了回复 :)


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