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


        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);
        效果与之前一致。
  • 相关阅读:
    Practice II 字符串
    Euleriar Path 入门
    2-SAT 入门
    Practice I 图论
    游戏中寻找学习JAVA的乐趣之坦克大战系列5-坦克的动态参数
    JQuery教程:实现轮播图效果
    HTML表格应用
    菜鸟Vue学习笔记(三)
    Java成神路上之设计模式系列教程之一
    JVM垃圾回收机制之对象回收算法
  • 原文地址:https://www.cnblogs.com/E-WALKER/p/4386546.html
Copyright © 2020-2023  润新知