This problem could be bad class design or ignorance - please bear with me:
I have 2 classes - Chip (which implements INotifyPropertyChanged and represents a single poker chip) and ChipSet, which implements INotifyPropertyChanged and has an ObservableCollection of Chip.
I have a Datagrid which is bound to the Chip ObservableCollection and a Textblock which is bound to ChipSet.
ie.开发者_C百科 gridChips.ItemsSource = chipset.Chips;
The Chip class has 3 properties (for simplicity) - NumberPerPlayer, ChipValue and TotalValuePerPlayer. TotalValuePerPlayer does not have a property set or associated private member variable like the other 2 - it is dynamically based off the product of ChipValue and NumberPerPlayer.
The grid binds to all 3 of these values and shows these 3 columns. Only the first 2 are editable and the 3rd one updates as the other 2 changes.
This works fine so far - I found that in order to get the TotalValuePerPlayer column to update if either of the other columns updated I had to add this field to PropertyChangedEventArgs (see code below).
My first question- Is this the best way of updating bound class fields that are based off other fields and do not change in the UI (you cannot edit TotalValuePerPlayer directly).
public int NumberPerPlayer
{
    get { return numberPerPlayer; }
    set
    {
        if (numberPerPlayer != value)
        {
            numberPerPlayer = value;
            OnPropertyChanged("NumberPerPlayer");
            OnPropertyChanged("TotalValuePerPlayer");
        }
    }
}
public decimal ChipValue
{
    get { return chipValue; }
    set
    {
        if (chipValue != value)
        {
            chipValue = value;
            //all columns that are based on this need to be updated
            OnPropertyChanged("ChipValue");
            OnPropertyChanged("TotalValuePerPlayer");
    }
}
public decimal TotalValuePerPlayer { get { return chipValue * numberPerPlayer; } }
public void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
My 2nd, main question is this: I then have a label which shows the total of all the TotalValuePerPlayer totals (stupidly called TotalTotalValuePerPlayer). I put this in the ChipSet class like this (it iterates through the ObservableCollection and sums the totals):
1            public decimal TotalTotalValuePerPlayer
2            {
3                get { 
4          decimal totalTotalValuePerPlayer = 0;
5                 foreach (Chip chip in chips)
6                  {
7                      totalTotalValuePerPlayer += chip.TotalValuePerPlayer;
8                  }
9                  return totalTotalValuePerPlayer;
10     }
11           }
So - the problem is that when either of the 2 columns (NumberPerPlayer or ChipValue) this field is based on in the UI changes, it does not update.
How do I tell the parent class - ChipSet, which has the TotalTotalValuePerPlayer member to be updated when one of its children class (Chip) members in it's ObservableCollection is updated?
If the TotalTotalValuePerPlayer was in the Chip class I could just notify it when the fields it was based off changed, but it is in the class above it?
Thanks for any advice!
Rodney
Hi there I believe you are going around this the correct way you just need to go a step further. Here are how would expect the classes to look:
Chip
public class Chip : INotifyPropertyChanged
{
    private int numberPerPlayer;
    public int NumberPerPlayer
    {
        get { return numberPerPlayer; }
        set
        {
            if (numberPerPlayer != value)
            {
                numberPerPlayer = value;
                OnPropertyChanged("NumberPerPlayer");
                OnPropertyChanged("TotalValuePerPlayer");
            }
        }
    }
    private decimal chipValue;
    public decimal ChipValue
    {
        get { return chipValue; }
        set
        {
            if (chipValue != value)
            {
                chipValue = value;
                //all columns that are based on this need to be updated
                OnPropertyChanged("ChipValue");
                OnPropertyChanged("TotalValuePerPlayer");
            }
        }
    }
    public decimal TotalValuePerPlayer 
    { 
        get
        { 
            return chipValue * numberPerPlayer; 
        } 
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
ChipSet
public class ChipSet : INotifyPropertyChanged
{
    public ChipSet()
    {
        foreach (var chip in Chips)
        {
            chip.PropertyChanged += (s, e) => { OnPropertyChanged("TotalTotalValuePerPlayer"); };
        }
    }
    public ObservableCollection<Chip> Chips { get; set; }
    public decimal TotalTotalValuePerPlayer
    {
        get
        {
            return Chips.Sum(x => x.TotalValuePerPlayer);
        }
    }
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
I have not tested this fully but it should point you in the right direction. Hope it helps.
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论