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.