简短说明
Button.CommandProperty 绑定到 ViewModel 的 SomeObject.SomeCommand 属性。当 SomeObject 的 SomeCommand 属性设置为 null 或整个 SomeObject 属性设置为 null 时,此按钮保持启用状态。在这种情况下如何禁用该按钮?
详细解释
我正在使用 MVVM 创建应用程序,其行为类似于浏览器:
主 view_model(对应于主窗口视图)具有工作区 view_model 列表。每个Workspace view_model对应windows的TabControl中的TabPage。
主 view_model 具有 CurrentWorkspace 属性,该属性对应于当前活动的 TabPage。
在主窗口中,有一个带有按钮的工具栏,它利用当前工作区提供的命令。例如,重载工作区数据的访问实现为:
<Button Name="btReload" Content="Reload"
Command="{Binding Path=CurrentWorkspace.ReloadCommand, UpdateSourceTrigger=PropertyChanged}"/>
我尝试通过创建 DataTriggers 来完成按钮禁用的任务,但触发器似乎只在第一次起作用,不再起作用:
<Button Name="btReload" Content="Reload"
Command="{Binding Path=CurrentWorkspace.ReloadCommand, UpdateSourceTrigger=PropertyChanged}">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CurrentWorkspace, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="{x:Null}">
<Setter Property="dxb:BarButtonItem.IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=CurrentPage.CurrentWorkspace, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="{x:Null}">
<Setter Property="dxb:BarButtonItem.IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
它看起来真的很愚蠢:就像 MS Word 一样,具有无文档客户区,同时工具栏中有许多可供单击的按钮(具有格式设置和其他特定于文档的功能)。请帮我, :)
附:当向工具栏添加 DataContext 绑定到 CurrentWorkspace 的按钮时,在窗口中激活或添加或删除工作区选项卡时,其 DataContextChanged 事件会正确触发。因此,问题出在 DataTrigger 中(或通常在 View 中),而不是 ViewModel 中。
UPDATE
我在VS2010上上传了示例项目,存档链接:http://www.filefactory.com/file/b43455e/n/WhatIfCommandIsNull.rar http://www.filefactory.com/file/b43455e/n/WhatIfCommandIsNull.rar
下面是它的描述。
- TextBox 绑定到 ViewModel.Data 属性
- 将 ViewModel 分配到 Window.DataContext 或从 Window.DataContext 中删除 ViewModel 可以通过单击两个按钮来完成 - 分别是 btAssignViewModel 和 btRemoveViewModel
- ViewModel 公开两个命令,其中一个将 ViewModel.Data 设置为字符串值,另一个将其设置为 NULL
- 这些命令通过 Button.Command 属性绑定到按钮 btSetData 和 btResetData
正如您所看到的,当 Window.DataContext 设置为 ViewModel 实例时,两个命令都可以正常工作,并且 ResetDataCommand.CanExecute 也可以工作(当 ViewModel.Data 为 NULL 时,ResetDataCommand.CanExecute 返回 false 并且按钮 btResetData 被禁用)。一旦 Window.DataContext 设置为 null,最后两个按钮将启用(对于前两个按钮,没有绑定任何命令)。
问题是以声明方式(通过触发器)实现接下来的四个规则:
- 如果 btAssignViewModel.DataContext 不为 null,则 btAssignViewModel.IsEnabled = false,否则为 true。
- 如果 btRemoveViewModel.DataContext 为 null,则 btRemoveViewModel.IsEnabled = false,否则为 true。
- 如果 ViewModel.Data 为 null,则 btSetData.IsEnabled = true,否则为 false。
- 如果 ViewModel.Data 为 null,则 btResetData.IsEnabled = false,否则为 true。
我认为前两个规则可以使用触发器来实现,后两个规则可以使用数据触发器来实现。但它们不起作用,所以我将它们从项目中删除了。