gpt4 book ai didi

c# - MVVM 的正确方法

转载 作者:行者123 更新时间:2023-11-30 19:29:00 25 4
gpt4 key购买 nike

我在其他问题中得到了关于如何实现 MVVM 的提示。当在 Student 类本身中进行更改时,我在将绑定(bind)更新传递到 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));
}
}
}

最佳答案

首先,我想推荐使用 MVVM 框架之一(我个人喜欢并使用 Caliburn.Micro ,但也有 MVVM Lightmyriad of others )。

(从现在开始我将使用 Caliburn.Micro 实现作为示例,因为这是我或多或少知道的一个框架)

为什么?好吧,它为您提供强类型的 NotifyOfPropertyChange(),内置事件聚合器、窗口管理器等等。这样您就不必每次都重新发明轮子。此外,Caliburn.Micro 的 Bootstrap 允许您嵌入您选择的 IoC 容器,如果您想采用无框架的 MVVM 方式,这对于 WPF 来说并不是那么容易。作为奖励,您可以拦截来自 GUI 控件的事件,因此您真的不必在代码隐藏中编写任何内容。

有些框架允许您按约定绑定(bind)并简化命令,但您必须仔细阅读,具体取决于您使用的框架。

其次,我强烈赞成完全重写 View 模型,以便它们成为独立的类而不是数据模型的包装器。您可以使用 AutomapperValueInjecter用于稍后映射。

那么你就有了 View 模型,例如:

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);
}
}
}

这就是 View 模型。然后在 View 模型中使用数据绑定(bind)、验证等。

您的 Student 类可以是例如一个简单的 DTO 或一个 EF 类或其他什么。为了简单起见,让我们使用愚蠢的 DTO:

public class Student
{
public string FirstName { get;set; }
public string LastName { get;set; }
}

因此,您仅在例如保存到数据库时才使用 DTO。就是这样。对于“常规”应用程序使用,您可以使用 View 模型进行 GUI 交互(绑定(bind))。

这就是 Automapper/ValueInjecter 发挥作用的地方,因为当您想“保存”更改/在任何地方添加新学生时,您必须将 View 模型映射到模型,例如:

//ValueInjecter
var dataModel = new Student().InjectFrom(this) as Student;
//AutoMapper
var dataModel = Mapper.Map<StudentViewModel, Student>(this);

就是这样。简单,容易,干净。按照您描述的方式,您想要更改基础模型。我不建议这样做,而是在可以通知您的 UI 的 View 模型上操作。您仅使用模型来“修改”数据存储中的数据(保存/更新/获取/删除)或以某种方式“传输”数据(例如使用 REST 网络服务),并使用 View 模型进行交互。

关于c# - MVVM 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13562220/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com