zoukankan      html  css  js  c++  java
  • xaml mvvm(2)之属性绑定

    通过微软INotifyPropertyChanged接口,可以实现对UI实时更新,不管是数据源或者目标对象,可以实现相互通知。

    下面我们根据INotifyPropertyChanged编写一个扩展类。该类是基于C#5.0特性,这里我们介绍一下System.Runtime.CompilerServices命名空间下的CallerMemberName特性,当RaisePropertyChanged的属性名称参数为空,而通过编译器可以智能加上,可以通过反编译工具知晓,这点改进这点很人性化。注:如果开发版本framework 4.0,则需要安装KB2468871补丁或者更新framework 4.0以上版本。

    为这个扩展类添加命名空间如下。

    1 using System;
    2 using System.Collections.Generic;
    3 using System.ComponentModel;
    4 using System.Diagnostics;
    5 using System.Linq.Expressions;
    6 using System.Reflection;
    7 using System.Runtime.CompilerServices;
     1 public class ObservableObject : INotifyPropertyChanged
     2 {
     3     public event PropertyChangedEventHandler PropertyChanged;
     4     protected PropertyChangedEventHandler PropertyChangedHandler
     5     {
     6         get
     7         {
     8             return this.PropertyChanged;
     9         }
    10     }
    11     [Conditional("DEBUG"), DebuggerStepThrough]
    12     public void VerifyPropertyName(string propertyName)
    13     {
    14         Type type = base.GetType();
    15         if (!string.IsNullOrEmpty(propertyName) && type.GetTypeInfo().GetDeclaredProperty(propertyName) == null)
    16         {
    17             throw new ArgumentException("Property not found", propertyName);
    18         }
    19     }
    20     protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    21     {
    22         PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
    23         if (propertyChanged != null)
    24         {
    25             propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    26         }
    27     }
    28     protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
    29     {
    30         PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
    31         if (propertyChanged != null)
    32         {
    33             string propertyName = ObservableObject.GetPropertyName<T>(propertyExpression);
    34             propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    35         }
    36     }
    37     protected static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
    38     {
    39         if (propertyExpression == null)
    40         {
    41             throw new ArgumentNullException("propertyExpression");
    42         }
    43         MemberExpression memberExpression = propertyExpression.Body as MemberExpression;
    44         if (memberExpression == null)
    45         {
    46             throw new ArgumentException("Invalid argument", "propertyExpression");
    47         }
    48         PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
    49         if (propertyInfo == null)
    50         {
    51             throw new ArgumentException("Argument is not a property", "propertyExpression");
    52         }
    53         return propertyInfo.Name;
    54     }
    55     protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue)
    56     {
    57         if (EqualityComparer<T>.Default.Equals(field, newValue))
    58         {
    59             return false;
    60         }
    61         field = newValue;
    62         this.RaisePropertyChanged<T>(propertyExpression);
    63         return true;
    64     }
    65     protected bool Set<T>(string propertyName, ref T field, T newValue)
    66     {
    67         if (EqualityComparer<T>.Default.Equals(field, newValue))
    68         {
    69             return false;
    70         }
    71         field = newValue;
    72         this.RaisePropertyChanged(propertyName);
    73         return true;
    74     }
    75     protected bool Set<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
    76     {
    77         return this.Set<T>(propertyName, ref field, newValue);
    78     }
    79 }

    下面我们来继承这个类编写一个Animal类对象。在这里我们用到RaisePropertyChanged三种不同的实现方式,达到一样的绑定效果。

     1 public class Animal : ObservableObject
     2 {
     3     private string m_Cat;
     4     public string Cat
     5     {
     6         get { return m_Cat; }
     7         set { m_Cat = value; RaisePropertyChanged("Cat"); }
     8     }
     9 
    10     private string m_Dog;
    11     public string Dog
    12     {
    13         get { return m_Dog; }
    14         set { m_Dog = value; RaisePropertyChanged(); }
    15     }
    16 
    17     private string m_Tiger;
    18     public string Tiger
    19     {
    20         get { return m_Tiger; }
    21         set { m_Tiger = value; RaisePropertyChanged(() => this.Tiger); }
    22     }
    23 }


    下面我们来建立model视图类。在该类中用的事件绑定和model对象实现,我们会在后续介绍。

     1 public class MainPageViewModel : Core.ViewModelBase
     2 {
     3     public MainPageViewModel()
     4     {
     5         MyAnimal = new Animal();
     6     }
     7 
     8     private Animal m_MyAnimal;
     9     public Animal MyAnimal
    10     {
    11         get { return m_MyAnimal; }
    12         set { m_MyAnimal = value; RaisePropertyChanged("MyAnimal"); }
    13     }
    14 
    15     public ICommand OKCommand
    16     {
    17         get
    18         {
    19             return new RelayCommand(() =>
    20             {
    21                 MyAnimal.Dog = "eating";
    22                 MyAnimal.Cat = "sleeping";
    23                 MyAnimal.Tiger = "hungry";
    24             });
    25         }
    26     }
    27 }


    前台xaml。

     1 <Grid DataContext="{Binding Path=MainPageViewModel}">
     2     <StackPanel>
     3         <StackPanel Orientation="Horizontal">
     4             <TextBlock FontSize="25" Text="cat is:" />
     5             <TextBlock FontSize="25" Text="{Binding MyAnimal.Cat}" />
     6         </StackPanel>
     7         <StackPanel Orientation="Horizontal">
     8             <TextBlock FontSize="25" Text="dog is:" />
     9             <TextBlock FontSize="25" Text="{Binding MyAnimal.Dog}" />
    10         </StackPanel>
    11         <StackPanel Orientation="Horizontal">
    12             <TextBlock FontSize="25" Text="Tiger is:" />
    13             <TextBlock FontSize="25" Text="{Binding MyAnimal.Tiger}" />
    14         </StackPanel>
    15         <Button Width="60" Content="OK" Command="{Binding OKCommand}" />
    16     </StackPanel>
    17 </Grid>


    运行效果。

  • 相关阅读:
    EasyUI combogrid 赋多个值
    EasyUI 打印当前页
    EasyUI 获取行ID,符合条件的添加样式
    JS 调用存储过程传递参数
    彻底解决Request Too Long的问题
    SQL处理XML
    DataTable排序
    EasyUI 动态生成列加分页
    SQL2012 分页(最新)
    计算数据库中各个表的数据量和每行记录所占用空间
  • 原文地址:https://www.cnblogs.com/yuefei/p/3799430.html
Copyright © 2011-2022 走看看