Ado*_*rez 2 c# wpf binding mvvm inotifypropertychanged
我对MVVM比较陌生,我试图了解INotifyPropertyChanged接口的工作原理以及如何在我的模型中实现它.我决定采用的方法是在每个Business Object类中实现它.
这种方法的问题在于,当我将View绑定到Base类中的属性时,该基类中的PropertyChanged事件永远不会被初始化(为null),因此当我的Model更改时,View不会刷新该元素的数据.我能够通过下面的例子重现问题.
我有一个Person Base类:
public class Person : INotifyPropertyChanged
{
#region INotifyProperty
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public String Name
{
get
{
return _name;
}
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
private String _name;
}
Run Code Online (Sandbox Code Playgroud)
我有一个继承自Person Base类的Employee类:
public class Employee : Person,INotifyPropertyChanged
{
#region INotifyProperty
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public String EmployeeID
{
get
{
return _employeeId;
}
set
{
_employeeId = value;
RaisePropertyChanged("EmployeeID");
}
}
private String _employeeId;
}
Run Code Online (Sandbox Code Playgroud)
在这里我的视图模型:
public class ViewModel : ViewModelBase<ViewModel>
{
private Employee _employee;
public ViewModel()
{
ChangeModelCommand = new RelayCommand(param=>this.ChangeModel() , param=>this.CanChangeModel);
Employee = new Employee()
{
Name = "BOB",EmployeeID = "1234"
};
}
public ICommand ChangeModelCommand { get; set; }
public Employee Employee
{
get
{
return _employee;
}
set
{
this._employee = value;
NotifyPropertyChanged(m=>m.Employee);
}
}
public void ChangeModel()
{
MessageBox.Show("CHANGING MODEL");
this.Employee.Name = "MIKE";
this.Employee.EmployeeID = "5678";
}
public bool CanChangeModel
{
get{ return true;}
}
}
Run Code Online (Sandbox Code Playgroud)
最后我的观点:
<Window.Resources>
<MVVM_NotificationTest:ViewModel x:Key="Model"></MVVM_NotificationTest:ViewModel>
</Window.Resources>
<Grid DataContext="{StaticResource Model}">
<StackPanel>
<Label Content="Employee Name"/>
<TextBox Text="{Binding Path=Employee.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Employee ID"/>
<TextBox Text="{Binding Path=Employee.EmployeeID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Change Model" Height="30" Width="100" Margin="5" Command="{Binding Path=ChangeModelCommand}"/>
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我在VM构造函数中初始化我的Employee VM Property,然后我有一个命令来修改EmployeeID(来自Employee类)和Name(来自Person类).但是,View中唯一更新的UI元素是EmployeeID而不是Name(我希望Bob更新为Mike).
在调试时我发现PropertyChanged事件在我的基类(Person)中始终为null.我还注意到,当我从Employee类中删除整个#INotifyProperty区域时,一切正常,因为它使用了Base Type事件和方法.
我遇到的问题是我所有当前的模型类都明确地实现了INotifyPropertyChanged.它们都定义了一个PropertyChanged事件并实现了RaisePropertyChanged方法,这显然会影响我在MVVM应用程序中的绑定.
最后,我想澄清一点,我不希望在我的ViewModel中包装我的Model属性并依赖VM INPC机制.我想使用我的模型INPC实现,而不必根据我是否继承基类型而有条件地删除INPC实现.
总之,我想知道在我的深层次模型中实现INPC的最佳方法是什么,这样继承不会像我们在本例中看到的那样破坏PropertyEvent传播,因此我的独立类也可以自给自足.任何想法或建议将不胜感激:)
只需使RaisePropertyChanged受到保护并将其移动到基类中.目前,您将有大量重复,这是不必要的.
像这样的东西:
protected virtual void RaisePropertyChanged(string propertyName);
Run Code Online (Sandbox Code Playgroud)
许多MVVM框架为您提供此功能.例如,PRISM有一个NotificationObject ViewModel基类.
| 归档时间: |
|
| 查看次数: |
4961 次 |
| 最近记录: |