Binding 如何在Silverlight数据网格上使用ObservableCollection更新动态字段

Binding 如何在Silverlight数据网格上使用ObservableCollection更新动态字段,binding,silverlight-4.0,Binding,Silverlight 4.0,这个问题可能是糟糕的课堂设计或无知-请容忍我: 我有两个类-Chip(实现INotifyPropertyChanged并表示单个扑克芯片)和ChipSet,实现INotifyPropertyChanged并具有可观察的芯片集合 我有一个绑定到芯片ObservableCollection的Datagrid和一个绑定到芯片组的Textblock 即gridChips.ItemsSource=芯片组.Chips Chip类有3个属性(为了简单起见)-NumberPerlayer、ChipValue和T

这个问题可能是糟糕的课堂设计或无知-请容忍我:

我有两个类-Chip(实现INotifyPropertyChanged并表示单个扑克芯片)和ChipSet,实现INotifyPropertyChanged并具有可观察的芯片集合

我有一个绑定到芯片ObservableCollection的Datagrid和一个绑定到芯片组的Textblock

即gridChips.ItemsSource=芯片组.Chips

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

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

到目前为止,这一切都很好——我发现为了在其他任何一列更新时更新TotalValuePerPlayer列,我必须将此字段添加到PropertyChangedEventArgs(请参见下面的代码)

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

公共十进制TotalValuePerPlayer { 获取{返回chipValue*numberPerPlayer;} }

我的第二个主要问题是:我有一个标签,上面显示了所有TotalValuePerPlayer总计的总数(愚蠢地称为TotalValuePerPlayer)。我将其放入芯片组类中,如下所示(它遍历ObservableCollection并对总数求和):

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

我如何告诉父类芯片组,当它的ObservableCollection中的一个子类(芯片)成员被更新时,它的TotalValuePerPlayer成员将被更新

如果TotalValuePerPlayer在芯片类中,我可以在它基于的字段发生更改时通知它,但它在它上面的类中

谢谢你的建议


罗德尼

你好,我相信你正在以正确的方式处理这件事,你只需要再往前走一步。下面是这些类的预期外观:

芯片

芯片组

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;
}
公共类芯片组:INotifyPropertyChanged
{
公共芯片组()
{
foreach(芯片中的var芯片)
{
chip.PropertyChanged+=(s,e)=>{OnPropertyChanged(“totalvalueperplayer”);};
}
}
公共可观测收集芯片{get;set;}
公共十进制TotalValuePerPlayer
{
得到
{
返回Chips.Sum(x=>x.TotalValuePerPlayer);
}
}
公共void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的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;
}
公共类芯片组:INotifyPropertyChanged
{
公共芯片组()
{
foreach(芯片中的var芯片)
{
chip.PropertyChanged+=(s,e)=>{OnPropertyChanged(“totalvalueperplayer”);};
}
}
公共可观测收集芯片{get;set;}
公共十进制TotalValuePerPlayer
{
得到
{
返回Chips.Sum(x=>x.TotalValuePerPlayer);
}
}
公共void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共事件属性更改事件处理程序属性更改;
}

我还没有完全测试过这一点,但它应该为您指出正确的方向。希望有帮助。

嗨,布朗蒂,谢谢你花时间回答-我有点困惑我需要做什么-这是芯片组构造器中的外观吗?chip.PropertyChanged+=(s,e)=>{OnPropertyChanged(“totalvalueperplayer”);};你在芯片类上连接eventhandler吗?你介意把这个循环完整地写出来吗?因为我不太清楚你的意思——非常感谢!Hi Rodney,芯片组构造函数中的所有代码都在ObservableCollection中的芯片上循环,并附加到每个芯片的PropertyChanged事件。因此,当芯片的任何属性发生变化时,它都会将芯片组的TotalValuePerPlayer更新到UI。这太棒了,感谢Blounty(我花了一段时间才弄明白语法——这对我来说是新的!)嗨Blounty,感谢您花时间回答-我有点困惑我需要做什么-这是芯片组构造器中的外观吗?chip.PropertyChanged+=(s,e)=>{OnPropertyChanged(“totalvalueperplayer”);};你在芯片类上连接eventhandler吗?你介意把这个循环完整地写出来吗?因为我不太清楚你的意思——非常感谢!Hi Rodney,芯片组构造函数中的所有代码都在ObservableCollection中的芯片上循环,并附加到每个芯片的PropertyChanged事件。因此,当芯片的任何属性发生变化时,它都会将芯片组的TotalValuePerPlayer更新到UI。这太棒了,谢谢Blounty(我花了一段时间才弄明白这种语法——这对我来说是新的!)
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           }
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;
}