Reputation: 81
I have a ControlTemplate built dynamically from a CollectionViewGroup.
I want it's visibility to be true only when all of it's items have a certain property set to true. I have somewhat accomplished this by:
XAML
<Button Visibility="{Binding Path=Items, Converter={StaticResource AllAcceptedToVis}}" Click="Button_ShipmentComplete_Click" Width="150" Margin="100,0,0,0">Complete</Button>
C#
public class AllAcceptedToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var items = (IEnumerable<object>)value;
return items.Cast<MyObject>().All(m => m.Accepted) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new InvalidOperationException("AllAcceptedToVisibilityConverter can only be used OneWay.");
}
}
This works, but only when it loads. It does not check for changes after the initial creation, and I suspect because it's bound to a list of addresses (Items) rather than a property, so it actually detects no change in the list of addresses at all (they remain unchanged).
How can I accomplish the above, but have the binding dynamically monitor all Items property changes?
Upvotes: 1
Views: 326
Reputation: 25623
The problem here is that you are binding against the collection instance, so the binding will only reevaluate if and when you assign a new collection to Items
. Presumably, you are only setting Items
once, so the converter will only be invoked once. It will not be invoked when the collection is modified, nor will it be invoked when the items within the collection are modified. WPF bindings don't support those kinds of 'deep' dependencies, so you will need to find a different approach.
I recommend maintaining a separate property on your view model, e.g., AllItemsAccepted
, which you can bind to directly. It will be up to you to listen for additions, removals, and replacements on Items
, and to listen for property changes on any of the elements within Items
. When such a change occurs, you must reevaluate AllItemsAccepted
. Don't forget to raise a property change notification so any bindings on AllItemsAccepted
will be reevaluated.
Note that there is a concept of a MultiBinding
(and IMultiValueConverter
), but those are only useful if you are binding against a known, fixed set of values (e.g., two or more separate properties); they won't help you with a dynamic collection. I only bring them up to save you from going down a rabbit hole and coming up empty.
Upvotes: 1