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

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

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

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
 public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected PropertyChangedEventHandler PropertyChangedHandler
{
get
{
return this.PropertyChanged;
}
}
[Conditional("DEBUG"), DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
Type type = base.GetType();
if (!string.IsNullOrEmpty(propertyName) && type.GetTypeInfo().GetDeclaredProperty(propertyName) == null)
{
throw new ArgumentException("Property not found", propertyName);
}
}
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
string propertyName = ObservableObject.GetPropertyName<T>(propertyExpression);
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
protected static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
{
throw new ArgumentNullException("propertyExpression");
}
MemberExpression memberExpression = propertyExpression.Body as MemberExpression;
if (memberExpression == null)
{
throw new ArgumentException("Invalid argument", "propertyExpression");
}
PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
if (propertyInfo == null)
{
throw new ArgumentException("Argument is not a property", "propertyExpression");
}
return propertyInfo.Name;
}
protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue)
{
if (EqualityComparer<T>.Default.Equals(field, newValue))
{
return false;
}
field = newValue;
this.RaisePropertyChanged<T>(propertyExpression);
return true;
}
protected bool Set<T>(string propertyName, ref T field, T newValue)
{
if (EqualityComparer<T>.Default.Equals(field, newValue))
{
return false;
}
field = newValue;
this.RaisePropertyChanged(propertyName);
return true;
}
protected bool Set<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
return this.Set<T>(propertyName, ref field, newValue);
}
}

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

 public class Animal : ObservableObject
{
private string m_Cat;
public string Cat
{
get { return m_Cat; }
set { m_Cat = value; RaisePropertyChanged("Cat"); }
} private string m_Dog;
public string Dog
{
get { return m_Dog; }
set { m_Dog = value; RaisePropertyChanged(); }
} private string m_Tiger;
public string Tiger
{
get { return m_Tiger; }
set { m_Tiger = value; RaisePropertyChanged(() => this.Tiger); }
}
}

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

 public class MainPageViewModel : Core.ViewModelBase
{
public MainPageViewModel()
{
MyAnimal = new Animal();
} private Animal m_MyAnimal;
public Animal MyAnimal
{
get { return m_MyAnimal; }
set { m_MyAnimal = value; RaisePropertyChanged("MyAnimal"); }
} public ICommand OKCommand
{
get
{
return new RelayCommand(() =>
{
MyAnimal.Dog = "eating";
MyAnimal.Cat = "sleeping";
MyAnimal.Tiger = "hungry";
});
}
}
}

前台xaml。

 <Grid DataContext="{Binding Path=MainPageViewModel}">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="" Text="cat is:" />
<TextBlock FontSize="" Text="{Binding MyAnimal.Cat}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="" Text="dog is:" />
<TextBlock FontSize="" Text="{Binding MyAnimal.Dog}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="" Text="Tiger is:" />
<TextBlock FontSize="" Text="{Binding MyAnimal.Tiger}" />
</StackPanel>
<Button Width="" Content="OK" Command="{Binding OKCommand}" />
</StackPanel>
</Grid>

运行效果。

xaml mvvm(2)之属性绑定的更多相关文章

  1. WPF使用MVVM(一)-属性绑定

    WPF使用MVVM(一)-属性绑定 简单介绍MVVM MVVM是Model(数据类型),View(界面),ViewModel(数据与界面之间的桥梁)的缩写,是一种编程模式,优点一劳永逸,初步增加一些逻 ...

  2. xaml mvvm(1)之结构

    在微软winstore.wp和silverlight中xaml是用来构建UI视图的标记语言,全名Extensible Application Markup Language.在结构上类似于html,但 ...

  3. 【WPF】如何把一个枚举属性绑定到多个RadioButton

    一.说明 很多时候,我们要把一个枚举的属性的绑定到一组RadioButton上.大家都知道是使用IValueConverter来做,但到底怎么做才好? 而且多个RadioButton的Checked和 ...

  4. WPF属性绑定实现双向变化

    WPF依赖项属性可以实现属性的绑定,成功绑定之后只要修改后台绑定的属性,即可UI同步自动更新绑定的值,无需手动刷新界面:同样,前台的值变化后,通过获取绑定的属性值也可获取UI变化后的值,实现双向变化的 ...

  5. 2019-11-29-WPF-依赖属性绑定不上调试方法

    原文:2019-11-29-WPF-依赖属性绑定不上调试方法 title author date CreateTime categories WPF 依赖属性绑定不上调试方法 lindexi 2019 ...

  6. 2019-8-2-WPF-依赖属性绑定不上调试方法

    title author date CreateTime categories WPF 依赖属性绑定不上调试方法 lindexi 2019-08-02 19:56:32 +0800 2019-8-2 ...

  7. Knockoutjs实例 - 属性绑定(Bindings)之流程控制(Control flow)

    一.foreach binding 使用此功能可以方便我们循环遍历输出某个数组.集合中的内容. (1).循环遍历输出数组 View Row Code 1 <script type="t ...

  8. grootJs的属性绑定指令

    index6.html 绑定文本text gt-text="{属性名}" 绑定标签属性attr gt-attr="vm属性名称(标签属性,value表达式)" ...

  9. 控制文本和外观------Attr Binding(attr属性绑定)

    Attr Binding(attr属性绑定) 目的 attr 绑定提供了一种方式可以设置DOM元素的任何属性值.你可以设置img的src属性,连接的href属性.使用绑定,当模型属性改变的时候,它会自 ...

随机推荐

  1. [转]Java IDE 之 IntelliJ IDEA 2017

    参考链接1:http://blog.csdn.net/u012364631/article/details/47682011 IDEA Community(社区版) 使用Maven创建Web工程 并部 ...

  2. java之RestTemplate的访问应用

    一.REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格.它是 ...

  3. UE4 的json读写方式

    转自:http://blog.csdn.net/cartzhang/article/details/41009343 JSON 的解析有很多开源库.UE4的JSON使用在代码的Public->S ...

  4. C#直接解析Json键值对

    string test_json = "{\"name\":\"tom\",\"nickname\":\"tony\&q ...

  5. OpenCL 矢量存取

    ▶ 函数 vloadn 和 vstoren 来实现全局存储器和局部存储器之间的向量拷贝 ● 代码 #include <stdio.h> #include <stdlib.h> ...

  6. leetcode877

    public class Solution { public bool StoneGame(int[] piles) { return true; } } 这问题很不好...

  7. Linux学习-linux系统下python升级到python3.6步骤详解,以及遇到的问题解决

    说明:一般linux会自带pyhton2.7 1.首先下载源tar包 可利用linux自带下载工具wget下载,如下所示: wget http://www.python.org/ftp/python/ ...

  8. So you've been rejected, now what? On appeals in peer-reviewed publications(From Wiley Exchanges)

    Getting rejected stinks. Wouldn’t it be great if we could appeal people’s decisions in life? Imagine ...

  9. 119. Pascal's Triangle II (Graph; WFS)

    Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3 ...

  10. OAuth2.0协议之新浪微博接口演示

    新浪微博接口调用数据代码: <?php /** * @ Author : LiBo * @ Date : 2013-10-25 * @ File : weiboapi.php * * @ 说明: ...