开发者

How to update a dynamic field using ObservableCollection on a Silverlight datagrid

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜