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 时,所有数据都转到了字符串