Search code examples
.netwpfinotifypropertychanged

NotifyPropertyChanged In a Class That Was Passed A Collection When An Item In The Collection Changes


I am passing a collection to UseSimpleClass. I would like UseSimpleClass property SimpleClassColCountChecked get to fire in when a value in a collection passed to UseSimpleClass changes.

In real life the collection is some user preferences and as they page through a useSimpleClass collection I want to preserve their preferences.

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private UseSimpleClass useSimpleClass;

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }


    public MainWindow()
    {
        InitializeComponent();
        List<SimpleClass> simpleCollection = new List<SimpleClass>();
        simpleCollection.Add(new SimpleClass());
        simpleCollection.Add(new SimpleClass());
        simpleCollection.Add(new SimpleClass());
        useSimpleClass = new UseSimpleClass(simpleCollection);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        useSimpleClass.SimpleClassCol[1].Checked = true;
    }
}

public class SimpleClass : INotifyPropertyChanged
{
    private bool _checked = false;

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public bool Checked 
    { 
        get { return _checked; } 
        set 
        {   
            _checked = value;
            NotifyPropertyChanged("Checked");
            // clearly the next line does not work but that is what I want
            NotifyPropertyChanged("SimpleClassColCountChecked");
        }
    }
}

public class UseSimpleClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public List<SimpleClass> SimpleClassCol { get; private set; }

    public Int32 SimpleClassColCountChecked
    {
        get
        {
            return (SimpleClassCol.Where(sc => sc.Checked).Count());
        }
    }

    public UseSimpleClass (List<SimpleClass> simpleClassCol)
    { SimpleClassCol = simpleClassCol; }
}

Solution

  • This way, you can handle PropertyChanged event of SimpleClass in UseSimpleClass.

    public UseSimpleClass (List<SimpleClass> simpleClassCol)
    { 
        SimpleClassCol = simpleClassCol; 
        foreach (var item in SimpleClassCol)
        {
            item.PropertyChanged += HandlePropertyChanged;
        }
    }
    
    private void HandlePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Checked")
            {
                NotifyPropertyChanged("SimpleClassColCountChecked");
            }
        }
    

    For each item in source (simpleClassCol) you start listening for PropertyChanged event. May be it is not so expensive.

    If it will be a ListBox (ListView), you can use SelectedItems collection to achive such behavior. So you will need two collection - first will contain whole items, second - selected items.

    EDIT: The main part I forgot - is that you should specify DataContext of your MainWindow

    Easy app

    so, in the code behind

    public MainWindow()
    {
        InitializeComponent();
        List<SimpleClass> simpleCollection = new List<SimpleClass>();
        simpleCollection.Add(new SimpleClass());
        simpleCollection.Add(new SimpleClass());
        simpleCollection.Add(new SimpleClass());
        useSimpleClass = new UseSimpleClass(simpleCollection);
        DataContext = useSimpleClass;
    }