浅谈WPF中的MVVM
来源:互联网 发布:守望先锋手机数据查询 编辑:程序博客网 时间:2024/05/29 18:56
浅谈WPF中的MVVM
一些基础知识
- WPF中的一个重要特性就是数据绑定(data binding),简单的说就是你有一些数据要显示给用户,你可以把数据和xaml进行绑定。
- WPF由2部分组成:描述GUI布局和效果的xaml文件,和xaml关联的cs文件。
- 如果你想最大程度上的复用你的代码,最好的方法就是使用MVVM(Model、View、ViewModel)模式,这样可以保证你的View部分包含的代码最少
一些关键点
- 你需要一个集合来保存数据,这个集合是ObservableCollection,而不能用List,Dictionary等。ObservableCollection的特点是在添加项、移除项或刷新整个列表时,此集合将提供通知
- 包括Window在内的所有的WPF控件都有一个DataContext
- 接口INotifyPropertyChanged是数据变化和GUI之间的桥梁
实例
再多的描述也不如一个实例更能够说明问题
我创建了一个Song类,用于存储一首歌曲中的信息,包括了歌曲名和歌手名
public class Song{ private string _songTitle; private string _artistName; public string SongTitle { get { return _songTitle; } set { _songTitle = value; } } public string ArtistName { get { return _artistName;} set { _artistName = value; } }}
设置DataContext方法有两种:
在xaml中:
<Window.DataContext> <local:SongViewModel /></Window.DataContext>
或者在cs文件中设置DataContext
public partial class MainWindow : Window{ SongViewModel _viewModel = new SongViewModel(); public MainWindow() { InitializeComponent(); base.DataContext = _viewModel; }}
在WPF中,这个Song类就是Model,而GUI则是View,ViewModel把这2层之间的数据进行关联。
然后我们继续创建ViewModel层
这个ViewModel层需要继承INotifyPropertyChanged接口,这样这个类中的某个属性值发生变化,我们会接到通知。
public class SongViewModel : INotifyPropertyChanged{ private Song _song; public Song Song { get { return _song; } set { _song = value; } } public string ArtistName { get { return Song.ArtistName; } set { if (Song.ArtistName != value) { Song.ArtistName = value; RaisePropertyChanged("ArtistName"); } } } public string SongTitle { get { return Song.SongTitle; } set { if (Song.SongTitle != value) { Song.SongTitle = value; RaisePropertyChanged("SongTitle"); } } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } }}
上面的代码中,首先检查属性的值是否真的发生变化if (Song.SongTitle != value),这样做可以在复杂的项目中,稍微提升一下性能,如果属性发生变化了,会引发PropertyChanged事件。
现在Model,ViewModel都已经完成,只差View了。MainWindow.xaml文件如下
<Window x:Class="WVVM.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WVVM" mc:Ignorable="d" Title="MainWindow" Height="201.288" Width="380.794"> <Window.DataContext> <local:SongViewModel></local:SongViewModel> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Label Grid.Column="0" Grid.Row="0" Content="SongTitle"></Label> <Label Grid.Column="0" Grid.Row="1" Content="Artist:"></Label> <Label Grid.Column="1" Grid.Row="1" Content="{Binding ArtistName}"></Label> <Label Grid.Column="1" Grid.Row="0" Content="{Binding SongTitle}"></Label> <Button Grid.Column="0" Grid.Row="2" Name="BtUpdate" Content="Update" Click="BtUpdate_OnClick"></Button> </Grid></Window>
xaml文件中,Button按钮有一个click事件,在这个事件中更新了viewMode的属性。
CS文件代码如下
private SongViewModel _viewModel; public MainWindow() { InitializeComponent(); _viewModel = (SongViewModel) base.DataContext; } private void BtUpdate_OnClick(object sender, RoutedEventArgs e) { _viewModel.ArtistName = "Adele"; _viewModel.SongTitle = "Hello"; }
像上文那样直接在GUI文件中绑定事件(Button的click事件),存在很多问题,WPF提供了一个更好的方法那就是ICommand。许多控件都有Command属性,它的绑定和Content,ItemSource的绑定方式相同。
继承ICommand需要实现2个方法:bool CanExecute(用于判断是否能够执行)和void Execute(在这里写你需要的代码,如更改SongTitle等)。
我建立了一个RelayCommand类来实现ICommand接口,代码如下
public class RelayCommand :ICommand { private readonly Func<Boolean> _canExecute; private readonly Action _execute; public RelayCommand(Action execute) : this(execute,null) { } public RelayCommand(Action execute, Func<Boolean> canExecute) { if(execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } public event EventHandler CanExecuteChanged { add { if (_canExecute != null) CommandManager.RequerySuggested += value; } remove { if (_canExecute != null) CommandManager.RequerySuggested -= value; } } [DebuggerStepThrough] public Boolean CanExecute(Object parameter) { return _canExecute == null ? true : _canExecute(); } public void Execute(Object parameter) { _execute(); } }
相应的,在SongViewModel类中,增加如下代码
void UpdateSongExecute() { //在这里执行更新数据的操作 ArtistName = "One Direction"; SongTitle = "Taken"; } bool CanUpdateSongExecute() { //在这里检查是否可以更新数据,我直接返回true了 return true; } public ICommand UpdateSong { get { return new RelayCommand(UpdateSongExecute,CanUpdateSongExecute);} }
此时,MainWindow.xaml文件中的Button,就不需要写click事件了,只需绑定Command即可
<Button Grid.Column="0" Grid.Row="2" Name="BtUpdate" Content="Update" Command="{Binding UpdateSong}"></Button>
- 浅谈WPF中的MVVM
- WPF中的MVVM模式
- WPF中的MVVM模式
- WPF中的MVVM模式
- WPF中的MVVM模式
- 浅谈Android中的MVVM模式
- MVVM模式和在WPF中的实现
- WPF-MVVM
- wpf-mvvm
- wpf mvvm
- WPF MvvM
- MVVM设计模式和WPF中的实现 (事件绑定)
- 浅谈MVC、MVP和MVVM,以及iOS中的MVC
- 浅谈 MVVM 设计模式在 Unity3D 中的设计与实施
- wpf mvvm模式 实例
- wpf sliverlight mvvm
- WPF之MVVM解析
- WPF之MVVM解析
- HTTP tunneling工具-端口转发
- ERROR C2514:XXX类没有构造函数
- Sublime text 3最新版破解方法
- HDU 2199 Can you solve this equation?(二分法求近似解)
- 打开文件和写文件的操作
- 浅谈WPF中的MVVM
- 基于C#的Windows定时关机系统的设计
- encodeURI 和 encodeURIComponent
- JAVA_final修饰符
- WeX5仿账本代码学习与分析
- 图像特征检测(Image Feature Detection)
- ALV demo:cl_salv_table
- ALV demo:cl_salv_table&nbsp…
- ALV demo:cl_salv_table&nbs…