zoukankan      html  css  js  c++  java
  • 初识MVVM(一)

    说明:关于什么是MVVM,园子中已经有很多文章做过介绍,自己对MVVM也有了初步的认识,算是一知半解吧。概念看起来总是有那么点抽象,简单的办法就是通过动手实践来进一步理解。

    从网上弄了几个案例,相信有人看过,在此只为了自己加深对MVVM的认识。

    1.目录结构,MVVM的目录结构大致如下:

    2.类图及实现过程

    简单的实现过程大致如下,首先就是手动实现两个接口:INotifyPropertyChanged,ICommand.

    2.1 INotifyPropertyChanged 接口的实现

     1 //1.继承INotifyPropertyChanged,要引用该命名空间
     2 using System.ComponentModel;
     3 
     4 namespace MVVMDemo.ViewModels
     5 {
     6     class NotificationObject:INotifyPropertyChanged
     7     {
     8         //(intface INotifyPropertyChanged,向客户端发出某些属性已更改的通知)
     9         //2.实现接口INotifyPropertyChanged
    10 
    11         public event PropertyChangedEventHandler PropertyChanged;
    12 
    13         public void RaisePropertyChanged(string propertyName)
    14         {
    15             if (this.PropertyChanged!=null)
    16             {
    17                 this.PropertyChanged.Invoke(this,new PropertyChangedEventArgs(propertyName));
    18             }
    19         }
    20     }
    21 }


    2.2 实现ICommand接口

     1   class DelegateCommand:ICommand
     2     {
     3         //ICommand 两个方法 CanExecute 和Execute,一个事件CanExecuteChanged
     4 
     5         public bool CanExecute(object parameter)
     6         {
     7             //throw new NotImplementedException();
     8             if (this.CanExecuteFunc==null)
     9             {
    10                 return true;
    11             }
    12           return   this.CanExecuteFunc(parameter);
    13         }
    14 
    15         public event EventHandler CanExecuteChanged;
    16 
    17         //Execute
    18         public void Execute(object parameter)
    19         {
    20            // throw new NotImplementedException();
    21             if (this.ExecuteAction==null)
    22             {
    23                 return;
    24             }
    25             this.ExecuteAction(parameter);
    26         }
    27 
    28         public Action<object> ExecuteAction { get; set; }
    29         public Func<object, bool> CanExecuteFunc { get; set; }
    30     }


    2.3 ViewModel的实现

    ViewModel中主要实现业务逻辑。本例要实现两数的加法运算:

    在这个步骤中首先要完成数据属性的定义,例如:

            private double input1;
    
            public double Input1
            {
                get { return input1; }
                set
                {
                    input1 = value;
                    this.RaisePropertyChanged("Input1");
                }
            }


    如果数据属性的数量比较多,那么输入总是要花费较多的时间,这里有个小技巧,就是使用快捷的输入方法,但是VS自身提供的代码段是有限的,幸运的是我们可以通过:工具>

    代码段管理器>添加来添加自定义的代码段。

    具体的方法是在安装路径下找到系统内置的代码段来修改,自定义自己需要的代码段。

     1 <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
     2     <CodeSnippet Format="1.0.0">
     3         <Header>
     4             <Title>propfull</Title>
     5             <Shortcut>propfull</Shortcut>
     6             <Description>属性和支持字段的代码段</Description>
     7             <Author>Microsoft Corporation</Author>
     8             <SnippetTypes>
     9                 <SnippetType>Expansion</SnippetType>
    10             </SnippetTypes>
    11         </Header>
    12         <Snippet>
    13             <Declarations>
    14                 <Literal>
    15                     <ID>type</ID>
    16                     <ToolTip>属性类型</ToolTip>
    17                     <Default>int</Default>
    18                 </Literal>
    19                 <Literal>
    20                     <ID>property</ID>
    21                     <ToolTip>属性名</ToolTip>
    22                     <Default>MyProperty</Default>
    23                 </Literal>
    24                 <Literal>
    25                     <ID>field</ID>
    26                     <ToolTip>支持此属性的变量</ToolTip>
    27                     <Default>myVar</Default>
    28                 </Literal>
    29             </Declarations>
    30             <Code Language="csharp">
    31                 <![CDATA[private $type$ $field$;
    32 
    33     public $type$ $property$
    34     {
    35         get { return $field$;}
    36         set { $field$ = value;}
    37     }
    38     $end$]]>
    39             </Code>
    40         </Snippet>
    41     </CodeSnippet>
    42 </CodeSnippets>

    主要修改Title,Shortcut和Code节点中的内容。例如:将上面的Code节点的内容改为如下

                <Code Language="csharp">
                <![CDATA[private $type$ $field$;
    
        public $type$ $property$
        {
            get { return $field$;}
            set 
            { 
                $field$ = value;
                this.RaisePropertyChanged("$property$");
            }
        }
        $end$]]>
                </Code>

    通过输入ShortCut节点中的名称,双击Tab键就可以快速输入代码。

    2)命令属性的实现

        public DelegateCommand AddCommand { get; set; }
            public DelegateCommand SaveCommand { get; set; }
    
            private void Add(object parameter)
            {
                this.Result = this.Input1 + this.Input2;
    
            }
    
            private void Save(object parameter)
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.ShowDialog();
               
            }

    3)在构造函数中实例化委托

    1  //构造函数
    2         public MainWindowViewModel()
    3         {
    4             this.AddCommand = new DelegateCommand();
    5             this.AddCommand.ExecuteAction = new Action<object>(this.Add);
    6 
    7             this.SaveCommand = new DelegateCommand();
    8             this.SaveCommand.ExecuteAction = new Action<object>(this.Save);
    9         }


    2.4绑定View

     

    1  <Button Content="Save" Height="38" HorizontalAlignment="Left" Margin="163,20,0,0" x:Name="btnSave" VerticalAlignment="Top" Width="110" Command="{Binding SaveCommand}" />
    2         <TextBox Background="{StaticResource {x:Static SystemColors.HighlightBrushKey}}" Grid.Row="1" Margin="6" Text="{Binding Input1}" />
    3         <TextBox Background="{StaticResource {x:Static SystemColors.HighlightBrushKey}}" Grid.Row="2" Margin="6" Text="{Binding Input2}" />
    4         <TextBox Background="{StaticResource {x:Static SystemColors.HighlightBrushKey}}" Grid.Row="3" Margin="6" Text="{Binding Result}" />
    5         <Button Content="Add" Height="38" HorizontalAlignment="Left" Margin="163,21,0,0" x:Name="btnAdd" VerticalAlignment="Top" Width="108" Grid.Row="4" Command="{Binding AddCommand}" />

    在后台代码中,只需做类似如下的操作:

    1 public partial class MainWindow : Window
    2     {
    3         public MainWindow()
    4         {
    5             InitializeComponent();
    6 
    7             this.DataContext = new MainWindowViewModel();
    8         }
    9     }

    即使我们将TextBox控件改为使用Slider,我们只需重新对Slider的进行重新绑定。如下:

     

     <Slider x:Name="slider1" Grid.Row="0" Background="LightBlue" Minimum="-100" Maximum="100" Margin="4"
                        Value="{Binding Input1}" />
                    <Slider x:Name="slider2" Grid.Row="1" Background="LightBlue" Minimum="-100" Maximum="100" Margin="4"
                        Value="{Binding Input2}" />
                    <Slider x:Name="slider3" Grid.Row="2" Background="LightBlue" Minimum="-100" Maximum="100" Margin="4"
                        Value="{Binding Result}" />
                    <Button x:Name="addButton" Grid.Row="3" Content="Add" Width="120" Height="80" Command="{Binding AddCommand}"/>


    说明:其实,没有必要自己手动实现两个接口,Prism为你完成了这两件事,你需要做的就是添加引用集并引用相应的命名空间。

  • 相关阅读:
    Eclipse慢慢学会的快捷键
    换行和flush()
    接口Interface
    对象的转型
    抽象类和抽象函数
    BufferedReader
    FileInputStream和FileReader
    Unable to instantiate receiver XXXXXX
    声明对象和定义数组
    Eclipse中文乱码问题
  • 原文地址:https://www.cnblogs.com/January/p/2439264.html
Copyright © 2011-2022 走看看