WPF ListBox w/ Header Button IsEnabled Question
I have a ListBox that displays items in need of approval, the ListBox.ItemTemplate is set to a viewmodel displaying the item's view in the list and each has an individual approve button.
I also have set the GroupStyle.HeaderTemplate to include an 'approve all' button, which I have working by using a behavior that uses the datacontext of the button (CollectionViewGroup) to send an event indicating which of the items should be approved.
My items require being updated from several databases before they are ready for approval, which happens asynchronously and their individual approve buttons enable once they are in a state where approval is valid.
My question is, how would I go about implementing disabling the 'approve all' button in the ListBox HeaderTemplate while the items in the CollectionViewGroup are awaiting their background updates.
I've been able to check them manually at the time of click not perform the action if they aren't all in the proper state but I'd like the UI to indicate they cannot be 'all approved' until the items have all updated to the proper state.
5 Replies
Would binding the IsEnabled of the button to Self and then using a converter to inspect the grouping state work? How would I get it to refresh if the status of an item in the grouping changes?
what due mean by refresh status ? can you please tell me more about that
I think I've managed something but it's not entirely performant and perhaps there is a better built in way.
@Abhishek_Dev Imagine a viewmodel w/ a CanApprove boolean, which on construction is false, during construction of the object a long running task is executed in a background thread to 'update' the item, when the update is finished CanApprove is 'true.'
I want to enable the button in the ListBox group header only if all the items in the CollectionViewGroup are CanApprove == true.
What I've managed so far is by using binding on the button's IsEnabled property, to the button's datacontext and using a converter to inspect the items in the CollectionViewGroup to see if they are indeed all 'CanApprove' And this worked fine for the initial population of the items but does not refresh.
So to get around that I made a class inherited from ObservableCollection and I subscribe to all the items in the collection's PropertyChanged event. In that event I check if the PropertyChanged event property name == "CanApprove" and if it does I do a check against the collections items to see if they all have "CanApprove" == true. if they do then I update the UI thread with a call to ObservableCollections OnCollectionChanged and provide a NotifyCollectionChangedAction.Reset, which seems to do the trick. It does stall the UI momentarily but unless there is a more performant way to achieve this I think I'm satisfied with it.
In MvvmToolkit there is a cool AsyncCommand that you can specify a task inside as the handler and the button on the UI would become disabled while the task was running, maybe you could try that approach?
AsyncRelayCommand - Community Toolkits for .NET
An asynchronous command whose sole purpose is to relay its functionality to other objects by invoking delegates