【问题标题】:How to update a dynamic field using ObservableCollection on a Silverlight datagrid如何在 Silverlight 数据网格上使用 ObservableCollection 更新动态字段
【发布时间】:2010-06-28 09:21:14
【问题描述】:

这个问题可能是糟糕的类设计或无知 - 请多多包涵:

我有 2 个类 - Chip(实现 INotifyPropertyChanged 并代表单个扑克筹码)和 ChipSet,它实现 INotifyPropertyChanged 并具有 Chip 的 ObservableCollection。

我有一个绑定到 Chip ObservableCollection 的 Datagrid 和一个绑定到 ChipSet 的 Textblock。

即。 gridChips.ItemsSource = 芯片组.芯片;

Chip 类有 3 个属性(为简单起见) - NumberPerPlayer、ChipValue 和 TotalValuePerPlayer。 TotalValuePerPlayer 没有像其他 2 个那样的属性集或关联的私有成员变量 - 它是动态基于 ChipValue 和 NumberPerPlayer 的乘积。

网格绑定到所有 3 个值并显示这 3 个列。只有前两个是可编辑的,第三个会随着其他两个的变化而更新。

到目前为止,这工作正常 - 我发现为了更新 TotalValuePerPlayer 列,如果其他列中的任何一个更新,我必须将此字段添加到 PropertyChangedEventArgs(参见下面的代码)。

我的第一个问题 - 这是更新基于其他字段且不会在 UI 中更改的绑定类字段的最佳方式(您不能直接编辑 TotalValuePerPlayer)。

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");
    }
}

公共小数 TotalValuePerPlayer { 得到 { 返回芯片值 * numberPerPlayer; } }

public void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

我的第二个主要问题是:然后我有一个显示所有 TotalValuePerPlayer 总数的标签(愚蠢地称为 TotalTotalValuePerPlayer)。我把它放在这样的 ChipSet 类中(它遍历 ObservableCollection 并对总数求和):

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           }

所以 - 问题在于,当 UI 中基于此字段的 2 列(NumberPerPlayer 或 ChipValue)中的任何一个发生更改时,它不会更新。

我如何告诉父类 - ChipSet,当它的 ObservableCollection 中的一个子类 (Chip) 成员更新时,它的 TotalTotalValuePerPlayer 成员要更新?

如果 TotalTotalValuePerPlayer 在 Chip 类中,我可以在它所基于的字段发生更改时通知它,但它在它上面的类中?

感谢您的建议!

罗德尼

【问题讨论】:

    标签: binding silverlight-4.0


    【解决方案1】:

    您好,我相信您正在以正确的方式解决这个问题,您只需要更进一步。以下是期望类的外观:

    芯片

    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));
            }
        }
    }
    

    芯片组

    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;
    }
    

    我尚未对此进行全面测试,但它应该会为您指明正确的方向。希望对您有所帮助。

    【讨论】:

    • 嗨 Blounty,感谢您抽出宝贵时间回答 - 我有点困惑我需要做什么 - 是芯片组构造函数中的外观吗? chip.PropertyChanged += (s, e) => { OnPropertyChanged("TotalTotalValuePerPlayer"); };您是否在 Chip 类上连接了一个事件处理程序?您是否介意完整地写出该循环,因为我不完全确定您的意思-非常感谢!
    • 嗨 Rodney,ChipSet 构造函数中的所有代码都在循环 ObservableCollection 中的芯片并附加到每个芯片的 PropertyChanged 事件。因此,当任何芯片的属性发生变化时,它都会将芯片集的 TotalTotalValuePerPlayer 更新到 UI。
    • 太棒了,谢谢 Blounty(我花了一段时间才弄明白这个语法——这对我来说是新的!)
    猜你喜欢
    • 2018-07-05
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多