Short description
Button.CommandProperty is bound to the SomeObject.SomeCommand ViewModel property. If the SomeCommand property of the SomeObject parameter is set to null or the SomeObject property is set to null, this button remains enabled. How can a button be disabled in such circumstances?
Detailed explanation
I create an application using MVVM, which behaves like a browser: The main view_model (which corresponds to the main window as a view) has a list of Workspace view_models. Each workspace view_model corresponds to a TabPage in the TabControl windows. The main view_model has a CurrentWorkspace property that corresponds to the currently active TabPage.
In the main window, where there is a toolbar with buttons, which uses the commands provided by CurrentWorkspace. For example, access to workspace overload data is implemented as:
<Button Name="btReload" Content="Reload" Command="{Binding Path=CurrentWorkspace.ReloadCommand, UpdateSourceTrigger=PropertyChanged}"/>
I tried to accomplish the task of disabling buttons by creating DataTriggers, but it seems that triggers only work for the first time and no more:
<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>
it looks really stupid: for example, MS Word with an undocumented client area and at the same time with a lot of buttons "ready to click" on the toolbar (with formatting and other functions specific to the document). Please help me:)
PS When you add a button to the toolbar with a DataContext tied to CurrentWorkspace, then the DataContextChanged event fires properly when you activate or add or remove a workspace tab in a window. So, the problem is somewhere in the DataTrigger (or in the view as in general), and not ViewModel (s) in it.
UPDATE
I uploaded a sample project to VS2010, a link to the archive: http://www.filefactory.com/file/b43455e/n/WhatIfCommandIsNull.rar
describe his description.
- TextBox bound to ViewModel.Data property li>
- Assignment or removal of ViewModel to / from Window.DataContext can be done by pressing two buttons - btAssignViewModel and btRemoveViewModel respectively
- ViewModel provides two commands, one of which sets ViewModel.Data to a string value, the other sets it to NULL
- These commands are bound to the btSetData and btResetData buttons through their Button.Command properties
As you can see, when Window.DataContext is installed in the ViewModel instance, both properly working commands and ResetDataCommand.CanExecute work (when ViewModel.Data is NULL, ResetDataCommand.CanExecute returns false and the btResetData button is disabled). If Window.DataContext is set to null, the last two buttons enable (no commands are bound for the first two trere elements).
The task is to implement declaratively (through triggers) the following four rules:
- If btAssignViewModel.DataContext is not null, then btAssignViewModel.IsEnabled = false, else true.
- If btRemoveViewModel.DataContext is null, then btRemoveViewModel.IsEnabled = false, else true.
- If ViewModel.Data is null, then btSetData.IsEnabled = true, else false.
- If ViewModel.Data is null, then btResetData.IsEnabled = false, else true.
I think that the first two rules can be implemented using triggers, the second second - using DataTriggers. But they do not work, so I deleted them from the project.