禁用父级时启用子控件

时间:2013-01-29 13:56:30

标签: wpf button hyperlink disabled-control

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

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

我需要启用超链接,但要禁用按钮。我怎样才能做到这一点?

以上只会导致两个控件都被禁用。

2 个答案:

答案 0 :(得分:0)

对象Hyperlink对属性IsEnabled有奇怪的了解。除了你提到的那个,即来自父级的完整值继承之外,还有另一个类似的。

对于已关闭(Hyperlink)的特定控件,

IsEnabled="False",设置(IsEnabled="True")将不会更新Hyperlink属性。解决方案 - 使用Hyperlink的相对来源(更多info)。

为了解决你的问题,我认为这不是解决问题的标准方法。所以我创建了一个Class,它有自己的依赖属性。它有它的属性MyIsEnabledMyStyle。正如您可能从标题中猜到的那样,第一个设置其属性IsEnabledMyStyle需要指定按钮样式,模拟IsEnabled="False"行为。

SimulateDisable Style

<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

<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>      

Listing of 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!");
}      

Output

enter image description here

P.S。对不起,迟到的回答:)。

答案 1 :(得分:0)

我通过创建一个简单的包装元素来解决这个问题,该元素打破了父元素的 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 IsEnabled="True">Testing</Hyperlink>default value)
  </ResetIsEnabled>
</Button>