Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing infinite loops when using INotifyPropertyChanged with a WPF treeview containing checkboxes

This is my first question so I apologise if it is not formatted perfectly.

I am new to WPF and MVVM and I have run into an issue I can't seem to figure out.

I have a treeview that displays a MenuItem hierarchy with a checkbox per MenuItem, both for Parent and Child nodes. The solution current allows a user to click on a parent node and all child items are checked / unchecked as required.

I now need to implement the reverse of this, where if a user clicks on one of the child nodes the parent node should be selected if it is not already selected.

The problem I currently have is that checking the parent node programmatically fires the INotifiedPropertyChanged event for the parent node which rechecks my child nodes.

How do I prevent this from happening?

Here is my MenuItem code:

public class MenuItem : INotifyPropertyChanged
    {
        string _name;
        List<MenuItem> _subItems = new List<MenuItem>();
        bool _isChecked;
        MenuItem _parent;

        public List<MenuItem> SubItems
        {
            get { return _subItems; }
            set
            {
                _subItems = value;
                RaisePropertyChanged("SubItems");
            }
        }

        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }

        public bool IsChecked
        {
            get { return _isChecked; }
            set
            {
                _isChecked = value;
                RaisePropertyChanged("IsChecked");
            }
        }

        public MenuItem Parent
        {
            get { return _parent; }
            set
            {
                _parent = value;
                RaisePropertyChanged("Parent");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            if (propertyName == "IsChecked")
            {
                if (Parent == null)
                {
                    foreach (MenuItem Child in _subItems)
                        Child.IsChecked = this.IsChecked;
                }

                //if (Parent != null)
                //{
                //    Parent.IsChecked = IsChecked ? true :Parent.IsChecked;
                //}
            }
        }
    }

The commented code above is where I am encountering the error.

Any guidance will be greatly appreciated.

like image 778
ThatChris Avatar asked Nov 25 '25 17:11

ThatChris


1 Answers

Just a bit more elaborated answer based on the one already written by OP

    public bool IsChecked
    {
        get { return _isChecked; }
        set
        {
            _isChecked = value;

            if (_parent == null)
            {
                foreach (MenuItem Child in _subItems)
                {
                    Child._isChecked = this._isChecked;
                    Child.RaisePropertyChanged("IsChecked");
                }
            }

            if (_parent != null)
            {
                _parent.NotifyChecked(_isChecked);
            }

            RaisePropertyChanged("IsChecked");
        }
    }
    public void NotifyChecked(bool childChecked) 
    { 
       _isChecked = childChecked;
        RaisePropertyChanged("IsChecked"); 
       if (_parent != null)
       {
           _parent.NotifyChecked(_isChecked);
       }
    }

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!