WPF简单MVVM实现

1. MVVM介绍:

    MVVM就是: Model -- 模型(现实中对象的抽象)

                    View -- UI(用户界面)

       ViewModel -- UI界面的抽象(给View提供数据,并响应View的操作)

2. 关键是要能准确的进行ViewModel的建模,处理好View与ViewModel之间的关系

    2.1. 只有2种关系:

               数据传递 --- 双向,使用Binding实现;

               操作传递 --- 单向(只从View传递给ViewModel),使用命令Command实现;

3. 开始

   3.1. 首先创建NotificationObject,它是所以ViewModel的基类

         因为要使用Binding,而ViewModel就充当数据源的角色,而要实现当值有变化时会自动响应,就必须实现INotifyPropertyChanged接口,代码如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace MVVMTest.ViewModels
 9 {
10     public class NotificationObject:INotifyPropertyChanged
11     {
12         public event PropertyChangedEventHandler PropertyChanged;
13 
14         public void RaisePropertyChanged(string property)
15         {
16             if (this.PropertyChanged != null)
17                 this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
18 
19         }
20     }
21 }
View Code

   3.2.接着要创建DelegateCommand,实现了ICommand接口,用来处理View发送到ViewModel的命令,代码如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows.Input;
 7 
 8 namespace MVVMTest.Commands
 9 {
10     public class DelegateCommand:ICommand
11     {
12         public bool CanExecute(object parameter)
13         {
14             if (this.CanExecuteFunc == null)
15             {
16                 return true;
17             }
18 
19              return this.CanExecuteFunc(parameter);
20         }
21 
22         public event EventHandler CanExecuteChanged;
23 
24         public void Execute(object parameter)
25         {
26             if (this.ExecuteAction == null)
27             {
28                 return;
29             }
30             this.ExecuteAction(parameter);
31         }
32 
33         public Action<object> ExecuteAction { get; set; }
34         public Func<object, bool> CanExecuteFunc { get; set; }
35     }
36 }
View Code

   3.3.为了方便开发,这里推荐自定义一个code snippet(代码块):

        放到此目录下C:Program Files (x86)Microsoft Visual Studio 12.0VC#Snippets1033Visual C#

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 3     <CodeSnippet Format="1.0.0">
 4         <Header>
 5             <Title>propn</Title>
 6             <Shortcut>propn</Shortcut>
 7             <Description>Code snippet for NotificationObject property and backing field</Description>
 8             <Author>Microsoft Corporation</Author>
 9             <SnippetTypes>
10                 <SnippetType>Expansion</SnippetType>
11             </SnippetTypes>
12         </Header>
13         <Snippet>
14             <Declarations>
15                 <Literal>
16                     <ID>type</ID>
17                     <ToolTip>Property type</ToolTip>
18                     <Default>int</Default>
19                 </Literal>
20                 <Literal>
21                     <ID>property</ID>
22                     <ToolTip>Property name</ToolTip>
23                     <Default>MyProperty</Default>
24                 </Literal>
25                 <Literal>
26                     <ID>field</ID>
27                     <ToolTip>The variable backing this property</ToolTip>
28                     <Default>myVar</Default>
29                 </Literal>
30             </Declarations>
31             <Code Language="csharp"><![CDATA[private $type$ $field$;
32 
33     public $type$ $property$
34     {
35         get { return $field$;}
36         set {     
37             $field$ = value;
38             this.RaisePropertyChanged("$property$");
39         }
40     }
41     $end$]]>
42             </Code>
43         </Snippet>
44     </CodeSnippet>
45 </CodeSnippets>
View Code

   3.4. 由于这个例子较简单,所以没有设计到Model的设计,而直接到ViewModel的设计,一般的规则是每个View就有一个对应的ViewModel,而ViewModel是充当View的数据源的,所以只需要考虑View需要什么数据、含有哪些操作,创建MainWindow的ViewModel,MainWindowViewModel,代码如下:

 1 using MVVMTest.Commands;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace MVVMTest.ViewModels
 9 {
10     public class MainWindowViewModel:NotificationObject
11     {
12         private string txt1;
13 
14         public string Txt1
15         {
16             get { return txt1; }
17             set
18             {
19                 txt1 = value;
20                 this.RaisePropertyChanged("Txt1");
21             }
22         }
23 
24         private string txt2;
25 
26         public string Txt2
27         {
28             get { return txt2; }
29             set
30             {
31                 txt2 = value;
32                 this.RaisePropertyChanged("Txt2");
33             }
34         }
35 
36         private string result;
37 
38         public string Result
39         {
40             get { return result; }
41             set
42             {
43                 result = value;
44                 this.RaisePropertyChanged("Result");
45             }
46         }
47 
48         public DelegateCommand ConcatCommand { get; set; }
49         public void Concat(object parameter)
50         {
51             Result = Txt1 + " and " + Txt2;
52         }
53 
54 
55         public MainWindowViewModel()
56         {
57             ConcatCommand = new DelegateCommand();
58             ConcatCommand.ExecuteAction = new Action<object>(Concat);
59         }
60         
61         
62         
63     }
64 }
View Code

    3.4.将ViewModel作为数据源赋值给View的DataContext

 1 using MVVMTest.ViewModels;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 using System.Windows;
 8 using System.Windows.Controls;
 9 using System.Windows.Data;
10 using System.Windows.Documents;
11 using System.Windows.Input;
12 using System.Windows.Media;
13 using System.Windows.Media.Imaging;
14 using System.Windows.Navigation;
15 using System.Windows.Shapes;
16 
17 namespace MVVMTest
18 {
19     /// <summary>
20     /// Interaction logic for MainWindow.xaml
21     /// </summary>
22     public partial class MainWindow : Window
23     {
24         public MainWindow()
25         {
26             InitializeComponent();
27             this.DataContext = new MainWindowViewModel();
28         }
29     }
30 }
View Code

    3.5.在View中绑定数据:

 1 <Window x:Class="MVVMTest.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="MainWindow" Height="350" Width="525">
 5     <Grid>
 6         <TextBox Margin="40,51,311,216" Text="{Binding Txt1}"/>
 7         <TextBox Margin="230,51,114,216" Text="{Binding Txt2}"/>
 8         <TextBox Margin="128,152,176,139" Text="{Binding Result}"/>
 9         <Button Margin="313,241,64,23" Command="{Binding ConcatCommand}"/>
10     </Grid>
11 </Window>
View Code

源代码:http://yunpan.cn/c3c7AAXm4U2dP  访问密码 8788

                

相关推荐