WPF:一旦我在代码中设置了一个属性,它就会永远忽略 XAML 绑定......我该如何防止这种情况发生?

Posted

技术标签:

【中文标题】WPF:一旦我在代码中设置了一个属性,它就会永远忽略 XAML 绑定......我该如何防止这种情况发生?【英文标题】:WPF: Once I set a property in code, it ignores XAML binding forever more... how do I prevent that? 【发布时间】:2011-02-04 02:50:30 【问题描述】:

我有一个带有数据触发器的按钮,如果某个属性未设置为 true,则该数据触发器用于禁用该按钮:

<Button Name="ExtendButton" Click="ExtendButton_Click"  Margin="0,0,0,8">
    <Button.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="Binding IsConnected" Value="False">
                    <Setter Property="Button.IsEnabled" Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
</Button.Style>

这是一些非常简单的绑定,而且它工作得很好。我可以设置“IsConnected”真假和真假真假,我喜欢看到我的按钮自动神奇地被禁用,然后启用等等。

但是,在我的 Button_Click 事件中...我想:

    禁用按钮(通过使用 ExtendButton.IsEnabled = false;) 运行一些异步代码(访问服务器...大约需要 1 秒)。 重新启用按钮(通过使用 ExtendButton.IsEnabled = true;)

问题是,当我手动将 IsEnabled 设置为 true 或 false...我的 XAML 绑定将永远触发再次。这让我很伤心:(

希望 IsEnabled 是三态的... true 表示 true,false 表示 false,null 表示继承。但事实并非如此,那我该怎么办?

【问题讨论】:

【参考方案1】:

在 WPF 中有一个很多更好的方法来获得这个功能。这是commanding system,太棒了。任何按钮、菜单项、热键等都可以链接到一个 single 命令,该命令会自动处理启用/禁用(如您在程序中所希望的那样)。它还干净且可重复使用,而且非常易于使用。

例如,在我的一个应用程序中,我有一个“关于对话框”,当用户按 F1 时会显示该对话框。我通过实现ICommand 创建了一个名为AboutCommand 的命令。

public class AboutCommand:System.Windows.Input.ICommand

    public bool CanExecute(object parameter)
    
        return true; // in this case the command is never disabled
    

    public event EventHandler CanExecuteChanged
    
        // not needed in this case, but in commands when CanExecute actually
        // changes, this performs the "magic" of disabling/enabling your controls
        add  CommandManager.RequerySuggested += value; 
        remove  CommandManager.RequerySuggested -= value; 
    

    public void Execute(object parameter)
    
        new AboutWindow().ShowDialog(); //happens when the command is executed
    

然后,在我窗口的 xaml 中,我添加了*:

<Window.Resources>
    <local:AboutCommand x:Key="About"/>
</Window.Resources>

<Window.InputBindings>
    <KeyBinding Command="StaticResource About" Gesture="F1"/>
</Window.InputBindings>

您也可以将命令设置为像这样的按钮。

<Button Command="StaticResource About" Content="About this program"/>

如果AboutCommand.CanExecute() 返回 false,则 F1 键按钮都将被禁用。

*(实际上我的做法不同,因为我使用的是 MVVM 模式,但如果您不使用该模式,这将有效。)

【讨论】:

我还没有进入命令系统的东西......我一定会按照你的建议再看看它。 真的很厉害。 =) 我认为对于我当前的代码问题,我只是要添加另一个属性......但我会在前进的过程中研究/可能使用命令。非常感谢!【参考方案2】:

Benny 的回答提供了一种方法(也是一种极好的方法)。另一个是扩展您的模型以支持“异步操作”状态并添加另一个触发器来响应:

XAML:

<Style.Triggers>
  <DataTrigger Binding="Binding IsConnected" Value="False">
    <Setter Property="Button.IsEnabled" Value="False" />
  </DataTrigger>
  <DataTrigger Binding="Binding IsInAsyncOperation" Value="True">
    <Setter Property="Button.IsEnabled" Value="False" />
  </DataTrigger>
</Style.Triggers>

代码隐藏:

private void ExtendButton_Click(...)

  IsInAsyncOperation = true;
  // begin async operation


private void OnAsyncOperationComplete(...)

  // retrieve results etc.
  IsInAsyncOperation = false;

注意:您将在与 IsConnected 相同的类上定义 IsInAsyncOperation 属性;如果这是一个视图模型而不是 Window 类,那么您需要相应地调整代码隐藏。

【讨论】:

这是我正在考虑做的解决方案(因为我已经拥有一个属性,我为在我的 XAML 中塑造大量控件而创建了一个属性)......我会添加另一个,并使用它。

以上是关于WPF:一旦我在代码中设置了一个属性,它就会永远忽略 XAML 绑定......我该如何防止这种情况发生?的主要内容,如果未能解决你的问题,请参考以下文章

如何永远在后台模式下运行应用程序?

单击“保存”时状态未更新

WPF MVVM Enable/Disable telerik:RadComboBox inside GridViewDataColumn from ViewModel。

我在 pandas 中设置了我的数据类型,但是在转换为 pyspark 时,所有数据都转到了字符串

一旦在情节提要中设置了 UIButton,iOS 9.2 就无法以编程方式更改它的标题

WPF 限制扩展器的大小