Kal*_*ale 2 c# wpf binding mvvm
我在其他关于如何实现MVVM的问题中得到了提示.在Student类本身进行更改时(我在项目中发生了很多变化),我在将绑定更新传递给GUI时遇到了问题.有没有办法简化这些事情并以比实现更紧凑的方式使用它?或者这是实现MVVM的最先进技术?
class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<StudentViewModel> studentViewModels = new ObservableCollection<StudentViewModel>();
public ObservableCollection<StudentViewModel> StudentViewModels
{
get { return studentViewModels; }
}
public MainWindowViewModel()
{
studentViewModels.Add(new StudentViewModel());
studentViewModels.Add(new StudentViewModel());
studentViewModels.Add(new StudentViewModel());
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
class StudentViewModel : INotifyPropertyChanged
{
Student model;
public String StudentFirstName
{
get { return model.StudentFirstName; }
set { model.StudentFirstName = value; }
}
public String StudentLastName
{
get { return model.StudentLastName; }
set { model.StudentLastName = value; }
}
public StudentViewModel()
{
model = new Student();
this.model.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case "StudentFirstName": OnPropertyChanged("StudentFirstName"); break;
case "StudentLastName": OnPropertyChanged("StudentLastName"); break;
default: break;
}
};
}
public StudentViewModel(Student model)
{
this.model = model;
this.model.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case "StudentFirstName": OnPropertyChanged("StudentFirstName"); break;
case "StudentLastName": OnPropertyChanged("StudentLastName"); break;
default: break;
}
;
}
public void changeStudent()
{
model.changeStudent();
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
class Student : INotifyPropertyChanged
{
public String studentFirstName;
public String StudentFirstName
{
get { return studentFirstName; }
set
{
if (studentFirstName != value)
{
studentFirstName = value;
OnPropertyChanged("StudentFirstName");
}
}
}
public String studentLastName;
public String StudentLastName
{
get { return this.studentLastName; }
set
{
if (studentLastName != value)
{
studentLastName = value;
OnPropertyChanged("StudentLastName");
}
}
}
public Student() { }
public void changeStudent()
{
StudentLastName = "McRonald";
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我想使用MVVM框架的一个建议(我个人喜欢和使用Caliburn.Micro,但也有MVVM Light和别人的无数).
(我Caliburn.Micro将从现在开始使用实现作为示例,因为这是我或多或少知道的一个框架)
为什么?好吧,它为您提供强类型NotifyOfPropertyChange(),内置事件聚合器,窗口管理器等等.这样你就不必每次都重新发明轮子.此外,Caliburn.Micro的引导程序允许您烘焙您选择的IoC容器,如果您想要使用MVVM而不使用框架方式,那么使用WPF并不是那么容易.作为奖励,您可以拦截GUI控件中的事件,因此您实际上不必在代码隐藏中编写任何内容.
有些框架允许您按惯例绑定并简化命令,但您必须阅读它,具体取决于您使用的框架.
第二件事,我强烈赞成完全重写视图模型,因此它们是独立的类而不是数据模型的包装器.您可以使用Automapper或ValueInjecter稍后进行映射.
那么你有视图模型,例如:
public class StudentViewModel : PropertyChangedBase
{
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
firstName = value;
NotifyOfPropertyChange(() => FirstName);
}
}
private string lastName
public string LastName
{
get { return lastName; }
set
{
lastName = value;
NotifyOfPropertyChange(() => LastName);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是视图模型.然后在视图模型中使用数据绑定,验证等.
您的Student课程可以是简单的DTO或EF级或其他类.为简单起见,让我们选择哑巴DTO:
public class Student
{
public string FirstName { get;set; }
public string LastName { get;set; }
}
Run Code Online (Sandbox Code Playgroud)
因此,仅在保存到数据库时才使用DTO.就是这样.对于"常规"应用程序使用,GUI交互(绑定),您使用视图模型.
这就是Automapper/ValueInjecter发挥作用的地方,因为当您想要'保存'更改/在任何地方添加新学生时,您必须将视图模型映射到模型,例如:
//ValueInjecter
var dataModel = new Student().InjectFrom(this) as Student;
//AutoMapper
var dataModel = Mapper.Map<StudentViewModel, Student>(this);
Run Code Online (Sandbox Code Playgroud)
就是这样.简单,容易,干净.您描述它的方式,您想要更改基础模型.我建议不要这样做,操作视图模型而不是可以通知你的UI.您仅使用模型"修改"数据存储中的数据(保存/更新/获取/删除)或以某种方式"传输"数据(例如,使用REST Web服务),并使用视图模型进行交互.