I have an MVVM-based WPF application that relies on Caliburn.Micro.
In one view, I am displaying a DataGrid
and a Button
. The DataGrid
displays a collection of items, where the item class derives from PropertyChangedBase
.
The button should be enabled or disabled based on the contents in the editable DataGrid
cells. What is the most reliable approach to achieve this with Caliburn.Micro?
Schematically, this is what my code looks right now:
public class ItemViewModel : PropertyChangedBase { }
...
public class ItemsViewModel : PropertyChangedBase
{
private IObservableCollection<ItemViewModel> _items;
// This is the DataGrid in ItemsView
public IObservableCollection<ItemViewModel> Items
{
get { return _items; }
set
{
_items = value;
NotifyOfPropertyChange(() => Items);
}
}
// This is the button in ItemsView
public void DoWork() { }
// This is the button enable "switch" in ItemsView
public bool CanDoWork
{
get { return Items.All(item => item.NotifiableProperty == some_state); }
}
}
As the code stands, there is no notification to ItemsViewModel.CanDoWork
when one NotifiableProperty
is changed, for example when the user edits one cell in the ItemsView
´s DataGrid
. Hence, the DoWork
button enable state will never be changed.
One possible workaround is to add an (anonymous) event handler to every item in the Items
collection:
foreach (var item in Items)
item.PropertyChanged +=
(sender, args) => NotifyOfPropertyChange(() => CanDoWork);
but then I also need to keep track of when (if) items are added or removed from the Items
collection, or if the Items
collection is re-initialized altogether.
Is there a more elegant and reliable solution to this problem? I am sure there is, but so far I have not been able to find it.