-2

I have a class Animal. Within the class Animal I have a list of another class called Dogs.

class Animal
{
  List<Dog> Dogs;
  int CountNeutedDogs;


  class Dog
  {
     // some properties
     boolean neuted;
   }
 }

It's possible that the list can contain about 500 dogs at any one time. I want to have an event so that if the value of neuted property in a dog changes the CountNeutedDogs is informed and updated. How do I do this?

Edit

I should explain the list Dogs is bound to a datagrid. The user can change the neuted property from false to true and vice versa. I have a get & set for the property. So the neuted value can change and I need to update the CountNeutedDogs value which is why I was thinking of using an event but not sure how to do it.

mHelpMe
  • 6,336
  • 24
  • 75
  • 150
  • I think creating a nested class for `Dog` is a little bit strange. I would not create it as an inner class, because a `Dog` could also be used in a `Mammal` class. – Jeroen van Langen Sep 30 '13 at 09:19
  • Might I suggest that your object modelling is a little unusual. In the real world an Animal does not HAVE A dog (or dogs), rather for example a Pound might HAVE A collection of dogs, and a dog IS an Animal (i.e. is a subclass of). – Surfbutler Sep 30 '13 at 09:19
  • I appreciate that the object modelling is probably not correct. I just created this example (should have used a better one, lesson learnt for next time!) to find out how I would create an event in my Dog Class to update the property in my Animal class. – mHelpMe Sep 30 '13 at 09:22
  • Is this project created in WPF? – Jeroen van Langen Sep 30 '13 at 09:23
  • yes its an WPF application – mHelpMe Sep 30 '13 at 09:24
  • you can declare an event for value changed, and put the logic you want in an event handler. this is a possible duplicate for your question: [link](http://stackoverflow.com/questions/9963809/value-changed-eventhandler) – Moha the almighty camel Sep 30 '13 at 09:27
  • I think you mean *neutered*, not neuted. – dreamlax Sep 30 '13 at 10:11

2 Answers2

4

If you make CountNeutedDogs a property like so, it will always be correct without events updating:

int CountNeutedDogs
{
    get
    {
        return this.Dogs.Where(d => d.neuted).Count();
    }
}
Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
Ashigore
  • 4,618
  • 1
  • 19
  • 39
2

This is a follow-up on the Comments:

I made an example, (not tested!!) how you can solve this by implementing the ObservableCollection and INotifyPropertyChanged

public class Dog : INotifyPropertyChanged
{
    private bool _isNeutered;

    public bool IsNeutered 
    {
        get { return _isNeutered; }
        set 
        {
            if (_isNeutered != value)
            {
                _isNeutered = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("IsNeutered"));
            }
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

public class Animals : INotifyPropertyChanged
{
    private ObservableCollection<Dog> _dogs = new ObservableCollection<Dog>();

    public Animals()
    {
        _dogs.CollectionChanged += Dogs_CollectionChanged;
    }


    // NOTE, I haven't checked this!! But I think it should be something like this:
    private void Dogs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                foreach (INotifyPropertyChanged item in e.NewItems.OfType<INotifyPropertyChanged>())
                    item.PropertyChanged += Item_PropertyChanged;
                break;

            case NotifyCollectionChangedAction.Reset:
            case NotifyCollectionChangedAction.Remove:
                foreach (INotifyPropertyChanged item in e.OldItems.OfType<INotifyPropertyChanged>())
                    item.PropertyChanged -= Item_PropertyChanged;
                break;
        }

        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("NeuteredDogsCount"));
    }

    private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("NeuteredDogsCount"));
    }

    public IEnumerable<Dog> Dogs 
    { 
        get { return _dogs; } 
    }

    public int NeuteredDogsCount
    {
        get
        {
            return Dogs.Where(dog => dog.IsNeutered).Count();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

So when the collection changes, the notify of the NeuteredDogsCount property is sent. This way the bounded controls will re-evaluate the NeuteredDogsCount property.

Instead of 'normal' properties, the IsNeutered can be changed to a DependencyProperty.

Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
  • thanks for the code example. Is it possible to do something similar without making the Dog list an ObservableCollection? – mHelpMe Sep 30 '13 at 09:40
  • You can check over here: _BindingList_ http://msdn.microsoft.com/en-us/library/ms132679.aspx – Jeroen van Langen Sep 30 '13 at 09:43
  • 1
    @JeroenvanLangen This is quite an interesting way to do it, however, I don't believe this handles the case where a dog in the list is updated externally. Wouldn't you need to attach and detach to each Dog's PropertyChanged event when they are added and removed? – Ashigore Sep 30 '13 at 10:00