电脑版网站制作公司,wordpress弹窗登陆,页面设计零基础,做国外服务器网站MVVM是一种设计模式#xff0c;特别适用于WPF等XAML-based的应用程序开发。MVVM模式主要包含三个部分#xff1a;Model#xff08;模型#xff09;、View#xff08;视图#xff09;和ViewModel#xff08;视图模型#xff09;。
Model#xff08;模型#xff09;特别适用于WPF等XAML-based的应用程序开发。MVVM模式主要包含三个部分Model模型、View视图和ViewModel视图模型。
Model模型模型代表的是业务逻辑和数据。它包含了应用程序中用于处理的核心数据对象。模型通常包含业务规则、数据访问和存储逻辑。View视图视图是用户看到和与之交互的界面。在WPF中视图通常由XAML定义并且包含各种用户界面元素如按钮、文本框、列表等。ViewModel视图模型视图模型是视图的抽象它包含视图所需的所有数据和命令。视图模型通过实现INotifyPropertyChanged接口和使用ICommand对象将视图的状态和行为抽象化从而实现了视图和模型的解耦。
MVVM模式的主要优点是分离了视图和模型使得视图和业务逻辑之间的依赖性降低提高了代码的可维护性和可测试性。此外通过数据绑定和命令绑定MVVM模式可以减少大量的样板代码使得代码更加简洁和易于理解。 不使用MVVM的例子
在Winform中我们使用了事件驱动编程同样在WPF中我们也可以使用事件驱动编程。
事件驱动编程是一种编程范式程序的执行由外部事件决定。当一个事件发生时会触发与之关联的事件处理器EVent Handler。事件处理器是一个函数或方法用于响应特定事件。
流程图如下 这里通过WPF实现一个事件驱动编程的例子
首先是UI界面的xaml代码
Window x:Classdemo_11_2.MainWindowxmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:dhttp://schemas.microsoft.com/expression/blend/2008xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006xmlns:localclr-namespace:demo_11_2mc:IgnorabledTitleMainWindow Height450 Width800LoadedWindow_LoadedStackPanelToolBarLabel Content姓名:/LabelTextBox x:NamenameTextBox Width50/TextBoxLabel Content邮箱:/LabelTextBox x:NameemailTextBox Width100/TextBoxButton Content添加ClickAddUser/Button/ToolBarStackPanelDataGrid x:NamedataGrid1/DataGrid/StackPanel/StackPanel
/WindowUI界面如是 这里使用了两个事件窗体加载时间和按钮点击事件: LoadedWindow_LoadedButton Content添加ClickAddUser/Button 添加两个类用户类和用户管理类 public class User{public string? Name { get; set; }public string? Email { get; set; }} public class UserManager{public static ObservableCollectionUser DataBaseUsers new ObservableCollectionUser(){new User() { Name tom, Email 123qq.com },new User() { Name jerry, Email 456qq.com },new User() { Name speicher, Email 789qq.com }};public static ObservableCollectionUser GetUsers(){return DataBaseUsers;}public static void AddUser(User user){DataBaseUsers.Add(user);}}
窗体加载事件处理程序 private void Window_Loaded(object sender, RoutedEventArgs e){dataGrid1.ItemsSource UserManager.GetUsers();}
按钮点击事件处理程序
private void AddUser(object sender, RoutedEventArgs e)
{User user new User();user.Name nameTextBox.Text;user.Email emailTextBox.Text;UserManager.AddUser(user);MessageBox.Show(成功添加用户);
}
如此便可成功添加
使用MVVM的例子 上面使用的是事件驱动编程我们在winform开发中经常这样干。对于一些小项目这样做很方便但是如果业务逻辑很多这样做就难以维护因为UI与业务逻辑严重耦合。
使用MVVM首先新建一个Commands文件夹新建一个RelayComand类 public class RelayCommand:ICommand{public event EventHandler? CanExecuteChanged;private Actionobject _Excute { get; set; }private Predicateobject _CanExcute { get; set; }public RelayCommand(Actionobject ExcuteMethod, Predicateobject CanExcuteMeth){_Excute ExcuteMethod;_CanExcute CanExcuteMeth;}public bool CanExecute(object? parameter){return _CanExcute(parameter);}public void Execute(object? parameter){_Excute(parameter);}}
RelayCommand实现了ICommand接口。
先来介绍一下ICommand接口在WPF中ICommand是一个接口它定义了一种机制用于在用户界面(UI)中处理事件这种机制与用户界面的具体行为进行了解耦。这是实现MVVM设计模式的关键部分。
ICommand接口包含两个方法和一个事件
Execute(object parameter)当调用此命令时应执行的操作。CanExecute(object parameter)如果可以执行Execute方法则返回true否则返回false。这可以用于启用或禁用控件例如按钮。CanExecuteChanged事件当CanExecute的返回值可能发生更改时应引发此事件。
ICommand结构图如下 ICommand反编译代码
public interface ICommand{event EventHandler? CanExecuteChanged;bool CanExecute(object? parameter);void Execute(object? parameter);}继续说RelayCommand
RelayCommand是一种常用于WPF和MVVM模式的设计模式它是一种特殊的命令类型。在MVVM模式中RelayCommand允许将命令的处理逻辑从视图模型中分离出来使得视图模型不需要知道命令的具体执行逻辑从而实现了视图模型和命令处理逻辑的解耦。
RelayCommand通常包含两个主要部分CanExecute和Execute。CanExecute是一个返回布尔值的函数用于确定命令是否可以执行。Execute是一个执行命令的函数当CanExecute返回true时Execute将被调用。
这种设计模式使得你可以在不改变视图模型的情况下更改命令的处理逻辑提高了代码的可维护性和可重用性。
简单来说就是RelayCommand是ICommand接口的一个常见实现它允许你将Execute和CanExecute的逻辑定义为委托从而实现对命令的灵活处理。
RelayCommand类中定义两个委托 private Actionobject _Excute { get; set; }private Predicateobject _CanExcute { get; set; }
Actionobject是一个委托它封装了一个接受单个参数并且没有返回值的方法。这个参数的类型是object。
对应于这一部分 public void Execute(object? parameter){_Excute(parameter);}
Predicateobject是一个委托它封装了一个接受单个参数并返回一个bool值的方法。这个参数的类型是object。
public bool CanExecute(object? parameter)
{return _CanExcute(parameter);
}
其RelayCommand构造函数 public RelayCommand(Actionobject ExcuteMethod, Predicateobject CanExcuteMeth){_Excute ExcuteMethod;_CanExcute CanExcuteMeth;}
然后说一下ViewModel
ViewModel是一个抽象它代表了View的状态和行为。ViewModel包含了View所需的数据并提供了命令以响应View上的用户操作。ViewModel不知道View的具体实现它只知道如何提供View所需的状态和行为。
ViewModel的主要职责包括
数据绑定ViewModel提供了View所需的数据。这些数据通常是以属性的形式提供的当这些属性的值改变时ViewModel会通过实现INotifyPropertyChanged接口来通知View。命令绑定ViewModel提供了命令以响应View上的用户操作。这些命令通常是以ICommand接口的实现的形式提供的。视图逻辑ViewModel包含了View的逻辑例如决定何时显示或隐藏某个元素何时启用或禁用某个按钮等。
新建一个ViewModel文件夹在该文件夹中新建一个MainViewModel类
public class MainViewModel
{public ObservableCollectionUser Users { get; set; }public ICommand AddUserCommand { get; set; }public string? Name { get; set; }public string? Email { get; set; }public MainViewModel(){Users UserManager.GetUsers();AddUserCommand new RelayCommand(AddUser, CanAddUser);}private bool CanAddUser(object obj){return true;}private void AddUser(object obj){User user new User();user.Name Name;user.Email Email;UserManager.AddUser(user);}
} View与ViewModel之间的关系: VVM关系图
首先最重要的就是数据绑定,现在View的xaml如下
Windowx:Classdemo11_1.MainWindowxmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:dhttp://schemas.microsoft.com/expression/blend/2008xmlns:localclr-namespace:demo11_1xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006TitleMainWindowWidth800Height450mc:IgnorabledStackPanelToolBarLabel Contentname: /TextBox Width60 Text{Binding Name} /Label Contentemail: /TextBox Width120 Text{Binding Email} /ButtonWidth150Command{Binding AddUserCommand}ContentAdd //ToolBarStackPanelDataGrid ItemsSource{Binding Users} //StackPanel/StackPanel
/Windowcs如下 public partial class MainWindow : Window{public MainWindow(){InitializeComponent();MainViewModel mainViewModel new MainViewModel();this.DataContext mainViewModel;}} 下图这几处为数据绑定对应VVM关系图的DataBindings流程。 下图为命令绑定对应于关系图的Commands, 如此便实现了与事件驱动一样的添加效果。
但是VVM关系图中的Send Notifications还没有体现Send Notifications表示ViewModel中的更改会通知View。
现在我们来以一个例子说明一下Send Notifications是如何实现的。
在MainViewModel中添加一个测试命令 public ICommand AddUserCommand { get; set; }
构造函数添加如下 TestCommand new Commands.RelayCommand(Test, CanTest);
需要的方法如下 private bool CanTest(object obj){return true;}private void Test(object obj){Name demo;Email 1130qq.com;}
前台xaml代码加入 Button Content测试 Command{Binding TestCommand }/Button 现在去deubg我们会发现没有成功原因是我们的ViewModel没有实现INotifyPropertyChanged接口。
在WPF中INotifyPropertyChanged接口用于实现数据绑定中的属性更改通知。当绑定到UI元素的数据源中的属性值发生更改时INotifyPropertyChanged接口可以通知UI元素更新。
INotifyPropertyChanged接口只定义了一个事件PropertyChanged。当属性值发生更改时应触发此事件。事件参数PropertyChangedEventArgs包含更改的属性的名称。
现在我们的MainViewModel实现一下INotifyPropertyChanged接口如下所示 public class MainViewModel : INotifyPropertyChanged{public ObservableCollectionUser Users { get; set; }public ICommand AddUserCommand { get; set; }public ICommand TestCommand { get; set; }private string? _name;public string? Name{get { return _name; }set{if (_name ! value){_name value;OnPropertyChanged(nameof(Name));}}}private string? _email;public string? Email{get { return _email; }set{if (_email ! value){_email value;OnPropertyChanged(nameof(Email));}}}public MainViewModel(){Users UserManager.GetUsers();AddUserCommand new RelayCommand(AddUser, CanAddUser);TestCommand new RelayCommand(Test, CanTest);}private bool CanTest(object obj){return true;}private void Test(object obj){Name demo;Email 1130qq.com;}private bool CanAddUser(object obj){return true;}private void AddUser(object obj){User user new User();user.Name Name;user.Email Email;UserManager.AddUser(user);}public event PropertyChangedEventHandler? PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
如此便可通知前台界面消息框成功获取MainViewModel要发送的信息。 此过程对应VVM图中的SendNotifications。
现在来说ViewModel—Model。 VMM关系图 Model模型Model代表了业务逻辑和数据。它包含了应用程序中的数据和对数据的操作例如从数据库中获取数据或者向数据库中添加数据。Model是独立于UI的它不知道UI的存在。
ViewModel视图模型ViewModel是Model和View之间的桥梁。它包含了View所需的数据这些数据来自于Model并提供了命令以响应View上的用户操作。ViewModel将Model的数据转换为View可以显示的数据同时它也将View上的用户操作转换为对Model的操作。
这个例子中我们的数据来源于Model文件夹下的User类与UserManager类这里的send notifications 如何解释
首先我们修改MainViewModel类的Test方法 private void Test(object obj){Users[0].Name demo;Users[1].Email 1130qq.com;//Name demo;//Email 1130qq.com;}
发现现在并不会发送通知实现View上的修改这是因为User类并没有实现INotifyPropertyChanged接口现在修改User类实现INotifyPropertyChanged接口
public class User : INotifyPropertyChanged
{private string? _name;public string? Name{get { return _name; }set{if (_name ! value){_name value;OnPropertyChanged(nameof(Name));}}}private string? _email;public string? Email{get { return _email; }set{if (_email ! value){_email value;OnPropertyChanged(nameof(Email));}}}public event PropertyChangedEventHandler? PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}
}如此便实现了通知成功将表格中的小王修改为emo。 使用MVVM相关库请看这篇文章使用MVVM相关库了解MVVM模式