• [WPF]WPF中如何实现数据与表示分离。(二) —— Binding(上)


    在我的上一篇文章:[WPF]WPF中如何实现数据与表示分离。(一) —— XAML 中,我简单介绍了如何使用XAML描述应用程序的界面。比较遗憾的是,那篇文章其实和数据与表示分离的主题似乎不大。这一篇文章中,我们将重点讨论WPF的Binding功能。

    还是用ColorPicker来作为例子。现在我们需要将它的数据层和表示层进行划分。在这个例子中,数据层的业务逻辑很简单:能够根据给入的三个变量生成一个颜色值。如果将它描述为一个对象,可能是下面的结构。
     1    public class ColorPickerData
     2    {
     3        public ColorPickerData()
     4        { }
     5
     6        byte _red;
     7        byte _green;
     8        byte _blue;
     9        Brush _backgound;
    10
    11        public byte Red
    12        {
    13            get return this._red; }
    14            set 
    15            {
    16                this._red = value;
    17                OnValueChanged();
    18            }

    19        }

    20        public byte Green
    21        {
    22            get return this._green; }
    23            set 
    24            {
    25                this._green = value;
    26                OnValueChanged();
    27            }

    28        }

    29        public byte Blue
    30        {
    31            get return this._blue; }
    32            set
    33            {
    34                this._blue = value;
    35                OnValueChanged();
    36            }

    37        }

    38        public Brush Background
    39        {
    40            get return this._backgound; }
    41            set this._backgound = value; }
    42        }

    43
    44        private void OnValueChanged()
    45        {
    46            this._backgound = new SolidColorBrush(Color.FromRgb(this._red, this._green, this._blue));
    47        }

    48    }

    49
    (注意:以上代码仅为说明问题。对于实现方式,大家应该都有更好的想法。)
    然后表示层通过一定的途径将这些信息展示出来。

    于是,我们编写了如下的展示层XAML文件,试图让它能够很好的展示这个数据对象。
     1<Window x:Class="ColorPicker2.Window1"
     2    xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
     3    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
     4    Title="ColorPicker2"
     5    Height="130" Width="300"
     6    >
     7    <Grid>
     8        <Grid.RowDefinitions>
     9            <RowDefinition/>
    10            <RowDefinition/>
    11            <RowDefinition/>
    12        </Grid.RowDefinitions>
    13        <Grid.ColumnDefinitions>
    14            <ColumnDefinition Width="40"/>
    15            <ColumnDefinition Width="150"/>
    16            <ColumnDefinition/>
    17        </Grid.ColumnDefinitions>
    18
    19        <TextBlock Grid.Column="0" Grid.Row="0">Red:</TextBlock>
    20        <Slider Grid.Column="1" Grid.Row="0"
    21                Minimum="0" Maximum="255"/>
    22
    23        <TextBlock Grid.Column="0" Grid.Row="1">Green:</TextBlock>
    24        <Slider Grid.Column="1" Grid.Row="1"
    25                Minimum="0" Maximum="255"/>
    26
    27        <TextBlock Grid.Column="0" Grid.Row="2">Blue:</TextBlock>
    28        <Slider Grid.Column="1" Grid.Row="2"
    29                Minimum="0" Maximum="255"/>
    30
    31        <Border Grid.Column="2" Grid.Row="0" Grid.RowSpan="3" Margin="5,5,5,5">
    32            <Border BorderThickness="1" CornerRadius="5" BorderBrush="Gray"/>
    33        </Border>
    34    </Grid>
    35</Window>
    现在,看起来结构更加清晰一些了。但是,我们如何让数据层和表示层进行衔接呢?往往这些衔接的逻辑可能会使我们系统的层次界限变得模糊。最终变成了铁板一块。

    我们来看一下在WPF中是如何实现这种衔接的。下面的是完整的数据展示层XAML。
     1<?Mapping XmlNamespace="local" ClrNamespace="ColorPicker2"?>
     2<Window x:Class="ColorPicker2.Window1"
     3    xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
     4    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
     5    xmlns:l="local" 
     6    Title="ColorPicker2"
     7    Height="130" Width="300"
     8    >
     9    <Grid>
    10        <Grid.Resources>
    11            <l:ColorPickerData x:Key="colorPickerData"/>
    12        </Grid.Resources>
    13        <Grid.DataContext>
    14            <Binding Source="{StaticResource colorPickerData}"/>
    15        </Grid.DataContext>
    16        <Grid.RowDefinitions>
    17            <RowDefinition/>
    18            <RowDefinition/>
    19            <RowDefinition/>
    20        </Grid.RowDefinitions>
    21        <Grid.ColumnDefinitions>
    22            <ColumnDefinition Width="40"/>
    23            <ColumnDefinition Width="150"/>
    24            <ColumnDefinition/>
    25        </Grid.ColumnDefinitions>
    26
    27        <TextBlock Grid.Column="0" Grid.Row="0">Red:</TextBlock>
    28        <Slider Grid.Column="1" Grid.Row="0"
    29                Minimum="0" Maximum="255" Value="{Binding Path=Red}"/>
    30
    31        <TextBlock Grid.Column="0" Grid.Row="1">Green:</TextBlock>
    32        <Slider Grid.Column="1" Grid.Row="1"
    33                Minimum="0" Maximum="255" Value="{Binding Path=Green}"/>
    34
    35        <TextBlock Grid.Column="0" Grid.Row="2">Blue:</TextBlock>
    36        <Slider Grid.Column="1" Grid.Row="2"
    37                Minimum="0" Maximum="255" Value="{Binding Path=Blue}"/>
    38
    39        <Border Grid.Column="2" Grid.Row="0" Grid.RowSpan="3" Margin="5, 5, 5, 5">
    40            <Border BorderThickness="1" CornerRadius="5" BorderBrush="Gray" Background="{Binding Path=Background}"/>
    41        </Border>
    42    </Grid>
    43</Window>
    与前一个XAML不同的地方主要在于黄色标注的部分。

    在行10-12中,我们将一个ColorPickerData数据包作为一个资源嵌入到这个XAML中来。并且将Grid的当前数据内容映射到这个数据包上(行13-15声明)。

    然后将后面的三个Slider的Value属性分别绑在数据包的几个不同的属性上。将Border的Background也绑定到数据包的Background属性上。

    Ok,看起来展示层已经描述的很清楚了。WPF项目组的一个PM(产品经理)看着这个设计露出了非常满足的笑容。清晰,明了,解决了大多数的用户需求。如果你是WPF项目组中的一个开发人员,现在你一定会跳得很高。

    “不可能,我怎么知道数据层什么时候变化了?”
    “不可能,你所描述的结构,我必须使用反射来读取数据,这样的性能将是无法接受的。”
    “不可能…………”你想了想,说:“对不起,麻烦问一下,‘{Binding Path=Blue}’似乎没有见过,代表什么呢?” -_-!

    Ok,这一切都是可能的。在下一篇文章里,我们将讨论微软是如何解决这些问题的。
  • 相关阅读:
    设计模式----工厂模式
    设计模式----简单工厂
    log4net使用详解
    link/Extended dependency 无法显示连接
    Abp框架之执行Update-Database 命令系列错误
    Index API
    使用Java客户端操作elasticsearch(二)
    elasticsearch之分词插件使用
    使用Java Low Level REST Client操作elasticsearch
    js如何获取隐藏的元素的高度
  • 原文地址:https://www.cnblogs.com/Cajon/p/320546.html
Copyright © 2020-2023  润新知