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

WPF - Notify ViewModel when object property is changed

我是 WPF 和 MVVM(以及一般编程)的新手,对于菜鸟问题​​提前表示抱歉,但我真的很想在 MVVM 中完成这项工作

我有一个 ObservableCollection class 和我使用它的 ViewModel,现在我想每次在 UI 中更改 "Role" 时计算 ViewModel 中的 OreMineTotal 和 OreTransportTotal(两个方式绑定)。

这现在有效,但仅当我从 ObservableCollection 添加或删除项目时才有效。

第一个问题 为什么当我在 UI 中更改玩家角色时,ViewModel 中的玩家 ObservableCollection setter 没有触发。

第二名 如何在 MVVM 中解决这个问题,我想知道如何从 ViewModel

intercept/subscribe 到 Player class 中的 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");
        }
    }
    ...........

每当一个项目添加到您的 ObservableCollection 时,您需要向该项目添加一个 PropertyChanged 事件处理程序并使用它来更新您的总数。

每当从您的 ObservableCollection 中删除一个项目时,您都需要删除该处理程序。

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

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

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

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

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

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