WPF - IsEnabled 绑定到 DependencyProperty 无法正常工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/966274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:32:35  来源:igfitidea点击:

WPF - IsEnabled Binding to DependencyProperty not working properly

wpfbuttonbindingdependency-propertiesisenabled

提问by Gus Cavalcanti

I have a dependency property defined in my window as below:

我在我的窗口中定义了一个依赖属性,如下所示:

public static readonly DependencyProperty IsGenericUserProperty = DependencyProperty.Register("IsGenericUser", typeof (bool), typeof (MainWindow));
public bool IsGenericUser
{
    get { return (bool) GetValue(IsGenericUserProperty); }
    set { SetValue(IsGenericUserProperty, value); }
}

On my window's constructor I set the data context of the container holding the button:

在窗口的构造函数中,我设置了包含按钮的容器的数据上下文:

QuickListButtonsStackPanel.DataContext = this;

I am binding the dependency property to the IsEnabled property of a button:

我将依赖属性绑定到按钮的 IsEnabled 属性:

<Button IsEnabled="{Binding IsGenericUser}" .../>

At startup IsGenericUser is true, so the button is enabled. When I set IsGenericUser to false, the button gets disabled. However, if I make IsGenericUser true again, nothing happens to the button and it remains disabled. What am I doing wrong?

启动时 IsGenericUser 为 true,因此该按钮已启用。当我将 IsGenericUser 设置为 false 时,按钮被禁用。但是,如果我再次将 IsGenericUser 设为 true,则该按钮不会发生任何变化并且它仍然处于禁用状态。我究竟做错了什么?

Thanks!

谢谢!

edit: Here is the style I am using with the button. This style is causing the issue (if the button has no custom style it works fine):

编辑:这是我与按钮一起使用的样式。这种样式导致了问题(如果按钮没有自定义样式,它可以正常工作):

<Style x:Key="BlackButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <ControlTemplate.Resources>
                    <Storyboard x:Key="MouseOverActivating">
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2F2F2F"/>
                            <SplineColorKeyFrame KeyTime="00:00:00.1270000" Value="#FF2391FF"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                    <Storyboard x:Key="MouseOverDeactivating">
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="rectangle">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2391FF"/>
                            <SplineColorKeyFrame KeyTime="00:00:00.2200000" Value="#FF2F2F2F"/>

                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                    <Storyboard x:Key="PressActivating">
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2391FF"/>
                            <SplineColorKeyFrame KeyTime="00:00:00.1370000" Value="#FF48D6FF"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                    <Storyboard x:Key="PressedDeactivating" FillBehavior="Stop" >
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="rectangle">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF48D6FF"/>
                            <SplineColorKeyFrame KeyTime="00:00:00.2370000" Value="#FF2391FF"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                    <Storyboard x:Key="DisableActivating">
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#FFA7A7A7"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </ControlTemplate.Resources>
                <Grid>
                    <Rectangle Stroke="Transparent" RadiusX="5" RadiusY="5" x:Name="rectangle">
                        <Rectangle.Fill>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FF000000" Offset="0"/>
                                <GradientStop Color="#FF2F2F2F" Offset="1"/>
                            </LinearGradientBrush>
                        </Rectangle.Fill>
                    </Rectangle>
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True" OpacityMask="{x:Null}"/>
                    <Rectangle Stroke="Transparent" RadiusX="5" RadiusY="5" x:Name="WhiteGlow">
                        <Rectangle.Fill>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#5BFFFFFF" Offset="0"/>
                                <GradientStop Color="#00FFFFFF" Offset="0.5"/>
                            </LinearGradientBrush>
                        </Rectangle.Fill>
                    </Rectangle>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsCancel" Value="False"/>
                    <EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
                    <Trigger Property="IsFocused" Value="True">
                        <Trigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOverActivating}" x:Name="MouseOverActivating_BeginStoryboard2"/>
                        </Trigger.ExitActions>
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOverActivating}" x:Name="MouseOverActivating_BeginStoryboard1"/>
                        </Trigger.EnterActions>
                    </Trigger>
                    <Trigger Property="IsDefaulted" Value="True"/>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Trigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOverDeactivating}" x:Name="MouseOverDeactivating_BeginStoryboard"/>
                        </Trigger.ExitActions>
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOverActivating}" x:Name="MouseOverActivating_BeginStoryboard"/>
                        </Trigger.EnterActions>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard x:Name="PressActivating_BeginStoryboard" Storyboard="{StaticResource PressActivating}"/>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard x:Name="PressedDeactivating_BeginStoryboard" Storyboard="{StaticResource PressedDeactivating}"/>
                        </Trigger.ExitActions>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource DisableActivating}" x:Name="DisableActivating_BeginStoryboard"/>
                        </Trigger.EnterActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

回答by rmoore

How are you setting the property to False/True? If I copy your code in as-is, it works perfectly. There has to be something else going on that you may not expect to effect it, like an animation on the button or something that is clearing the binding. Is there more code that you can post that may help clarify what could be doing this?

您如何将属性设置为 False/True?如果我按原样复制您的代码,它就可以完美运行。必须有其他事情发生,您可能不会期望它会影响它,例如按钮上的动画或清除绑定的东西。您是否可以发布更多代码来帮助阐明可能会这样做?

Here's the code I tested as well:

这是我测试的代码:

<Window x:Class="WpfApplication6.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    Height="300"
    Width="300">
<Grid>
    <StackPanel x:Name="QuickListButtonsStackPanel">
        <Button IsEnabled="{Binding IsGenericUser}"
                Content="Bound Button" />
        <Button Content="Change Binding"
                Click="Button_Click" />
    </StackPanel>
</Grid>

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        QuickListButtonsStackPanel.DataContext = this;
    }
    public static readonly DependencyProperty IsGenericUserProperty =
        DependencyProperty.Register(
            "IsGenericUser",
            typeof(bool),
            typeof(Window1));

    public bool IsGenericUser
    {
        get { return (bool)GetValue(IsGenericUserProperty); }
        set { SetValue(IsGenericUserProperty, value); }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        IsGenericUser = !IsGenericUser;
    }
}

EDIT: You can add a text box as well to see if it is working,

编辑:您也可以添加一个文本框以查看它是否有效,

<Button x:Name="uiButton"
        IsEnabled="{Binding IsGenericUser}"
        Style="{StaticResource BlackButtonStyle}"
        Content="Bound Button"/>
<TextBlock Text="{Binding ElementName=uiButton, Path=IsEnabled}" />

It looks like the problem is just with the style's storyboards, if you add that, does it still show that IsEnabled is false when it shouldn't be?

看起来问题仅在于样式的故事板,如果您添加它,它是否仍然显示 IsEnabled 不应该是假的?

回答by Jarrett Meyer

Try

尝试

<Button IsEnabled={Binding Path=IsGenericUser}" ... />

The Path=shouldn't be required, but it might make a differerce.

Path=不应该是必需的,但它可能使一个differerce。

And by using the thisin the data context, are you sure that's right? Wouldn't that make the control itself to the context. I've not seen the rest of your code, but that just doesn't seem right.

通过this在数据上下文中使用 ,您确定这是正确的吗?这不会使控件本身适应上下文。我还没有看到您的其余代码,但这似乎不对。

回答by Gus Cavalcanti

1) Created a new storyboard called DisableDeactivating and set the FillBehavior="Stop" (Nicholas' suggestion) 2) Then, added a BeginStoryboard for DisableDeactivating in the Trigger.ExitActions of the IsEnabled = false trigger.

1) 创建一个名为 DisableDeactivation 的新故事板并设置 FillBehavior="Stop" (Nicholas 的建议) 2) 然后,在 IsEnabled = false 触发器的 Trigger.ExitActions 中添加一个用于 DisableDeactivation 的 BeginStoryboard。

回答by GeorgiG

If anyone encounters the same problem - it's very possible your DataContext isn't set or is dynamically changed to another Object. It happens in some Templates that contain a lot of diverse Controls.

如果有人遇到同样的问题 - 很可能您的 DataContext 未设置或动态更改为另一个对象。它发生在一些包含许多不同控件的模板中。