MVVM(Model-View-ViewModel)模型浅析
MVVM模型类似于ASP.NET中的MVC模型
与之不同的是MVC模型实现了Model层和View层的分离,但是View的显示依赖于Model曾和Cotroller的控制
而MVVM模型实现了Model层和View层的完全隔离,
View和ViewModel之间主要通过Databinding来显示ViewModel数据,
同时View可以通知ViewModel数据的变化(设置Binding Mode);
用户操作通过绑定对应Command以通知ViewModel进行逻辑处理,
ViewModel通过消息更新View的显示。
下边通过一个简单的Demo的关键步骤解析下MVVM模型的用法,
一、创建好WP7应用程序项目,分别添加两个文件夹Model和ViewModel
在Model文件夹中创建实体类,这点 有点类似于MVC中Model层,形成用户操作数据数据和类的映射,
例如:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes;
namespace MVVMModel.Model { public class People { public string Name { get; set; } public string Address { get; set; } public string Telephone { get; set; }
public string Picture { get; set; } } }
同时再在Model文件夹中添加PeopleService类,通过创建一些方法方便获取People的数据
如下:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Collections.ObjectModel; using System.Collections.Generic; namespace MVVMModel.Model { public class PeopleService {
///获取源数据 public List<People> GetAllPeople() { List<People> people = new List<People>() { new People(){ Name="Olive", Address="北京", Telephone="1111111111", Picture="/Images/不甘心.jpg"}, new People(){ Name="Yao", Address="北京", Telephone="2222222222", Picture="/Images/纯洁.jpg"}, new People(){ Name="Momo", Address="北京", Telephone="333333333", Picture="/Images/多拉A梦.jpg"}, new People(){ Name="Xue", Address="北京", Telephone="4444444444", Picture="/Images/额.jpg"} }; return people; }
然后需要在ViewModel文件夹中添加MainViewModel类(核心类),作为Model层和View层交互的桥梁
如下:
public MainViewModel() { appName = "People Hub"; AppTitle = "Welcome To People Hub"; Peoples = new ObservableCollection<People>(peopleService.GetAllPeople()); } private PeopleService peopleService = new PeopleService();
public event PropertyChangedEventHandler PropertyChanged; private string appName; private string appTitle; public string AppName { get { return appName; } set { if (appName == value) return; appName=value; OnPropertyChanged("AppName"); } }
public string AppTitle { get { return appTitle; } set { if (appTitle == value) return; appTitle = value; OnPropertyChanged("AppTitle"); } }
public ObservableCollection<People> people; public ObservableCollection<People> Peoples { get { return people; } set { if (people == value) return; people = value; OnPropertyChanged("Peoples"); } } public void OnPropertyChanged(string propertyChangedName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyChangedName)); } 这是需要实现INotificatyChanged接口,在INotifyPropertyChanged接口在using System.ComponentModel命名空间下
这时就只需要在MainPage.xaml页进行绑定就可以了
首先引入命名空间:
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:MVVMModel.ViewModel" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
然后在页面资源里声明MainViewModel为页面资源
<phone:PhoneApplicationPage.Resources> <mv:MainViewModel x:Name="MainViewModel"></mv:MainViewModel>
。。。。。。
</phone:PhoneApplicationPage.Resources> 这时可能会提示你实例无法创建,只需要把项目生成一下就可以了,
然后就资源与相关控件绑定就可以,
<phone:PhoneApplicationPage.Resources> <mv:MainViewModel x:Name="MainViewModel"></mv:MainViewModel> <DataTemplate x:Name="PeopleTemplage" >//为ListBoxItem项创建的模板 <StackPanel Orientation="Vertical"> <TextBlock Text="{Binding Name}"/> <TextBlock Text="{Binding Address}"/> <TextBlock Text="{Binding Telephone}"/> <Image Source="{Binding Picture}" Width="200" Height="200" Stretch="Fill"/> </StackPanel> </DataTemplate> </phone:PhoneApplicationPage.Resources> <!--LayoutRoot 是包含所有页面内容的根网格--> <Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource MainViewModel}">//将整个MainViewModel绑定到顶层容器Grid上 <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions>
<!--TitlePanel 包含应用程序的名称和页标题--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="{Binding AppTitle}" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="{Binding AppName}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>
<!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox ItemsSource="{Binding Peoples}" ItemTemplate="{StaticResource PeopleTemplage}" Width="468" Height="270" Margin="6,6,-18,331"></ListBox> </Grid> </Grid>
这样就可以实现数据的绑定了运行就可以看到效果了
如果需要实现用户的添加删除等其他的操作,则需要将控件和Command进行绑定,
这样需要创建新的类例如添加,则需创建IAddCommd类,该类需要实现ICommand接口
主要有以下几个函数:
private readonly MainViewModel mainViewModel; public AddCommand(MainViewModel mainviewmodel) { mainViewModel = mainviewmodel; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) public void Execute(object parameter)//在这里边写需要的操作代码 { mainViewModel.AddPeople(mainViewModel.People); }
同时在MainViewModel里添加属性AddCommand,
在前台界面部分将AddCommand属性绑定到控件的Command属性上
如下:
<Button Content="Save" Height="72" HorizontalAlignment="Left" Margin="10,545,0,0" Name="btnSave" Command="{Binding AddCommand}" VerticalAlignment="Top" Width="160" />
这样就可以实现用户的操作了,在运行之前要注意AddCommand属性的初始化:
如下:
public MainViewModel() { appName = "People Hub"; AppTitle = "Welcome To People Hub"; Peoples = new ObservableCollection<People>(peopleService.GetAllPeople()); AddCommand = new AddCommand(this);
}
总结:刚开始接触MVVM模型看了之后感觉跟MVC模式有些相似之处,最大的突破在于View层和Model层的完全隔离,使得View层和Model层相互之间不再依赖影响,极大的方便了美工做出用户体验较好的UI,更方便了编程人员和美工的分工合作,极大的促进了开发效率。
另关于绑定Comman部分,由于篇幅有限只写了几个关键的点,希望有需要的朋友留个邮箱给发源码。(学习中)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构