Search code examples
c#wpf

Trigger another property update when a collection is modified


In my C# / WPF application, I have a class with several properties:

public class VariationDefinition
{
    public int VariationsCount => Variations == null ? 0 : Variations.Count;
    public ObservableCollection<ConditionVariation> Variations { get; private set; }

    public void RegenerateVariations()
    {
        //Initializes and fills the Variations collection
        //...
    }
}

On WPF side, there are several properties that are binded to these properties, for example:

<ListView ItemsSource="{Binding Variations}"/>
<TextBlock Text="{Binding VariationsCount}"/>

When RegenerateVariations is called, the ListView updates immediately, indicating that binding is working properly. However, TextBlock does not update. I assume that this is because change in the Variations collection does not trigger a NotifyPropertyChanged event in the VariationsCount property.

As I understand it, it is possible to subscribe to the ObservableCollection<T>.CollectionChanged Event (docs), but I don't know how to attach that to the VariationsCount property. I can't seem to find any examples, but I'm probably not looking for the right thing. Can you explain how to do it?


Solution

  • Instead of creating another variable, you can bind your UI code directly to the Count property of the ObservableCollection and it notifies the UI when the count changed as following

    <ListView ItemsSource="{Binding Variations}"/>
    <TextBlock Text="{Binding Variations.Count}"/>
    

    update

    if you don't like this approach, you can notify your UI by yourself first make your class implement INotifyPropertyChanged and subscribe to the collection change event as following

    public class VariationDefinition : INotifyPropertyChanged  
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        public VariationDefinition()
        {
            // subscribe on collection change
            Variations.CollectionChanged += (s, e) =>
            {
                // notify the UI that property VariationsCount is changed
                // and UI will update the new value
                PropertyChanged?.Invoke(this, new(nameof(VariationsCount)));
            };
        }
    
        public int VariationsCount => Variations?.Count ?? 0;
        public ObservableCollection<ConditionVariation> Variations { get; } = new();
         
    }