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。对你的提议非常有用。
允许您以双向方式绑定模型和视图。
我是 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。对你的提议非常有用。
允许您以双向方式绑定模型和视图。