WPF学习07:MVVM 预备知识之数据绑定_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > WPF学习07:MVVM 预备知识之数据绑定

WPF学习07:MVVM 预备知识之数据绑定

 2015/4/2 16:05:18  官文祥  程序员俱乐部  我要评论(0)
  • 摘要:MVVM是一种模式,而WPF的数据绑定机制是一种WPF内建的功能集,两者是不相关的。但是,借助WPF各种内建功能集,如数据绑定、命令、数据模板,我们可以高效的在WPF上实现MVVM。因此,我们需要对各种MVVM相关的WPF内建功能集进行了解,才能在扎实的基础上对MVVM进行学习与实践。本文是WPF学习03:ElementBinding的后续,将说明实现数据绑定的三个重点
  • 标签:学习 数据

    MVVM是一种模式,而WPF的数据绑定机制是一种WPF内建的功能集,两者是不相关的。

    但是,借助WPF各种内建功能集,如数据绑定、命令、数据模板,我们可以高效的在WPF上实现MVVM。因此,我们需要对各种MVVM相关的WPF内建功能集进行了解,才能在扎实的基础上对MVVM进行学习与实践。

    本文是WPF学习03:Element Binding的后续,将说明实现数据绑定的三个重点:DataContext INotifyPropertyChanged IValueConverter

 

MVVM简介

    MVVM将User Interface切成了3个部分,View、Model、View Model.

    三个部分区分如下:

    View:界面代码,并完成数据可视化。

    Model:一系列我们与业务层交互的类。

    View Model:1.将Model中需要显示的部分,转化为对View友好的数据。    2.管理View与View之间的交互。  

   image

    依赖关系如上图所示,V依赖于VM,反之不应该成立,VM依赖于M,反之亦不应成立。

    在完成了对数据绑定、命令、数据模板的理解后,我们再重新回来解释MVVM。


 

DataContext

    在WPF学习03:Element Binding中,我们只研究了如何在控件间实现数据绑定,在不指定ElementName时,Binding会在Source与RelativeSource也没有设置的情况下,一级一级的寻找DataContext,直到找到。

    例子

    image

<StackPanel HorizontalAlignment="Center" TextBlock.Foreground="#019AFF" DataContext="{x:Static Colors.White}">
    <!--指定Path,绑定对象的某个属性-->
    <TextBlock Text="{Binding Path=R}"></TextBlock>
    <TextBlock Text="{Binding Path=G}"></TextBlock>
    <TextBlock Text="{Binding Path=B}"></TextBlock>
    <!--不指定Path,绑定整个对象-->
    <TextBlock Text="{Binding}"></TextBlock>
</StackPanel>

     比较常用的情况下,我们将DataContext设置在最顶层元素,一般情况下为Window。

     我们可以在后台代码中配置DataContext:

public class Person
{
    private Int32 _age;
        
    public Int32 Age 
    {
        get { return _age; }
        set { _age = value; }
    }

    private String _name;

    public String Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    person = new Person() { Name = "Kenny", Age = 30 };
    this.DataContext = person;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    person.Name = "John Locke";
    person.Age = 40;
}

    XAML做的改动:

<StackPanel HorizontalAlignment="Center" TextBlock.Foreground="#019AFF">
    <TextBlock Text="{Binding Path=Name}"></TextBlock>
    <TextBlock Text="{Binding Path=Age}"></TextBlock>
    <Button Click="Button_Click">Click me</Button>
</StackPanel>

    效果如下:

    image

     我们可以看到的确显示了期望值,但是如果点击按键的话,是看不到任何变化的,接下来即解释原因与解决方法


 

INotifyPropertyChanged

    WPF内建的数据绑定机制中,Dependency Property不需额外做任何配置,即可在一般情况下建立数据绑定关系。WPF自建控件的各类属性都是依赖属性经传统的.Net属性包装而成。

    如果我们希望将数据绑定的源设为我们自己定义的对象的属性,且该属性不为依赖属性,那么就只有靠实现INotifyPropertyChanged接口,并在相应的属性改变时调用PropertyChanged事件以通知目标元素。

    我们将之前的后台代码做如下的改动:

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private Int32 _age;    
    public Int32 Age 
    {
        get { return _age; }
        set { 
            _age = value;
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this,new PropertyChangedEventArgs("Age"));
        }
    }

    private String _name;
    public String Name
    {
        get { return _name; }
        set {
            _name = value;
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
        }
    }

}

    效果如下:

    image

   


 

IValueConverter

    某些特殊的时候,源属性与目标属性是无法连接,需要进行转换,这时,就需要用到ValueConverter.直接给个例子:

    数据绑定实现根据年龄不同,文字显示同颜色,效果:

    imageimage

    XAML代码:

<TextBlock Text="{Binding Path=Name}"></TextBlock>
<TextBlock Name="AgeTextBlock" Text="{Binding Path=Age}">
<TextBlock.Foreground>
        <Binding Path="Age">
            <Binding.Converter>
                <local:TextBlockColorValueConverter></local:TextBlockColorValueConverter>
            </Binding.Converter>
        </Binding>
</TextBlock.Foreground>
</TextBlock>
    后台代码:
[ValueConversion(typeof(Boolean), typeof(Int32))]
public class TextBlockColorValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((int)value < 18)
            return new SolidColorBrush(Colors.Violet);
        else
            return new SolidColorBrush(Colors.Red);
    }

    //这里用不上数据从目标返回源,故返回null
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

 

数据绑定的后台代码实现

     之前的数据绑定都是用XAML实现的,在此给出后台代码实现数据绑定的方法,实现刚才的例子:

     首先给两个控件标个Name,并去掉之前的所有绑定相关代码:

<TextBlock Name="NameTextBlock"></TextBlock>
<TextBlock Name="AgeTextBlock"></TextBlock>

      后台代码:

var bind = new Binding("Name")
{
    Source = person,
};
NameTextBlock.SetBinding(TextBlock.TextProperty, bind);
bind = new Binding("Age")
{
    Source = person,
};
AgeTextBlock.SetBinding(TextBlock.TextProperty, bind);
bind = new Binding("Age")
{
    Source = person,
    Converter = new TextBlockColorValueConverter()
};
AgeTextBlock.SetBinding(TextBlock.ForegroundProperty, bind);
    效果与之前一致。
发表评论
用户名: 匿名