WPF - 更改对象属性时通知ViewModel

时间:2017-06-30 18:18:30

标签: c# wpf mvvm propertychanged

我是WPF和MVVM(以及一般编程)的新手,所以提前抱歉为了noobish问题,但我真的想在MVVM中完成这项工作

我有一个ObservableCollection类和ViewModel,我使用它,现在我想在每次更改我的UI中的“角色”(双向绑定)时在ViewModel中计算OreMineTotal和OreTransportTotal。

现在只能在我从ObservableCollection中添加或删除项目时使用。

第一次任务 为什么在我更改UI中的Player角色时,ViewModel中的Players ObservableCollection的setter不会触发。

第二 如何在MVVM中解决这个问题,我想知道如何拦截/订阅来自ViewModel的Player类中的RaisePropertyChanged(“Role”)

在winforms中我会处理它(鼠标点击或其他)事件,我改变了玩家角色,但我想做MVVM风格

namespace MiningCalc.Model
{
public class Player : INotifyPropertyChanged
{

    public Player()
    {
        items = new ObservableCollection<MinedItems>();
    }
    private string name;
    private string mass;
    private int fc;
    private int boost;
    private int log;
    private int role;
    private ObservableCollection<MinedItems> items;

    public ObservableCollection<MinedItems> Items
    {
        get
        {
            return items;
        }
        set
        {
            if (items != value)
            {
                items = value;
                RaisePropertyChanged("Items");
            }
        }
    }

    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            if (name != value)
            {
                name = value;
                RaisePropertyChanged("Name");
            }
        }
    }

    ...... other variables .....

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
    }
}

}

和ViewModel

namespace MiningCalc.ViewModel
{
class ViewModelPlayer : INotifyPropertyChanged
{
    private decimal oreMineTotal;
    private decimal oreTransportTotal;
    private ObservableCollection<Player> players;

    public ObservableCollection<Player> Players
    {
        get
        {
            return players;
        }
        set
        {
            players = value;
            OnPropertyChanged("Players");
            OnPropertyChanged("OreMineTotal"); //not working
            OnPropertyChanged("OreTransportTotal"); // not working
        }
    }

    public ViewModelPlayer()
    {
        players = new ObservableCollection<Player>();
        players.CollectionChanged += OnCollectionChanged;
        LoadLogCommand = new RelayCommand(LoadLog, LoadLog_CanExecute);
    }

    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        //System.Windows.MessageBox.Show("Firing");
        OnPropertyChanged("OreMineTotal");
        OnPropertyChanged("OreTransportTotal");
    }

    public decimal OreMineTotal
    {
        get
        {
            oreMineTotal = Players.Where(x => x.Role == 0).Sum(a => decimal.Parse(a.Mass, NumberStyles.Any));
            return oreMineTotal;
        }
        set
        {
            oreMineTotal = value;
            OnPropertyChanged("OreMineTotal");
        }
    }


    public decimal OreTransportTotal
    {
        get
        {
            oreTransportTotal = Players.Where(x => x.Role == 1).Sum(a => decimal.Parse(a.Mass, NumberStyles.Any));
            return oreTransportTotal;
        }
        set
        {
            oreTransportTotal = value;
            OnPropertyChanged("OreTransportTotal");
        }
    }
    ...........

2 个答案:

答案 0 :(得分:2)

每当项目添加到ObservableCollection时,您都需要为该项添加PropertyChanged事件处理程序,并使用它来更新总计。

每当从ObservableCollection移除某个项目时,您需要删除该处理程序。

每当在ObservableCollection中替换项目时,您需要从旧项目中删除处理程序并为新项目添加处理程序。

这通常在CollectionChanged处理程序内部使用NotifyCollectionChangedEventArgs的更改类型枚举上的switch语句实现。

目前您只跟踪对集合本身的更改。您还需要监控项目的更改:)

除此之外,这里没有MVVM问题。除了上述专家级MVVM之外,您的代码也是如此。没有进一步的MVVM方法来增强您的代码。

答案 1 :(得分:-1)

在C#中查看Dependency Properties Tutorial。对你的建议非常有用。

允许您以双向方式绑定模型和视图。