[WPF]WPF中如何实现数据与表示分离。(一) —— XAML

软件复用一直是现代软件工程所追求的目标。提高软件复用性的一个关键点就是“数据表示分离”(表示:数据的展示方式)。
这个系列文章将以“如何分离数据与表示”做为主线,能够概要的介绍一些在WPF中引入的新的编程技术和概念。

在这个系列里面,我们将使用Kevin Moore的ColorPicker作为一个例子,通过逐渐深入的引入WPF中的新概念,来演示这些新概念对我们的开发有什么好处。

首先,让我们来介绍一下ColorPicker可以干什么?
        ColorPicker运行效果如下图:
        [WPF]WPF中如何实现数据与表示分离。(一) —— XAML

通过拖动左边的Slider可以动态的改变右面预览窗口的背景颜色。

本系列文章将逐步的引入WPF中的概念,主要包括下面的几个步骤:
1. XAML
2. Binding
4. Convert.
3. Styling

我希望在每一阶段我们都尽量的将焦点集中在一个问题上,同时能够对这个问题相关的因素进行简单的介绍,以达到通过这个系列能够让大家对WPF有一个概括的了解。

OK, Let's GO...


在WPF中,微软引入了XAML(可扩展应用程序标记语言)的概念。其实XAML本不是一个新事物,在理论界已经经过多年的研究,应该说已经形成了一个相对成熟的体系。
简单来说,XAML就是一个应用程序界面的描述语言,(呵呵,这个描述可能并不准确,但是可能会更好理解一些)。就像我们以前编写VB程序或Delphi程序,会将界面按照一定的描述方式保存起来一样。
但是,XAML是基于XML的,因此,它与生俱来的具有XML的优势——跨平台,可扩展。

我们先来看一下如何用XAML来描述一个程序的界面:

< Window  x:Class ="Freezed.Window1"
    xmlns
="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns:x
="http://schemas.microsoft.com/winfx/xaml/2005"
    Title
="Color Picker"
    Height
="130"  Width ="300"
    
>
    
< Grid >
      <RowDefinition/>
      
<RowDefinition/>
      
<RowDefinition/>
      <ColumnDefinition Width="40"/>
      
<ColumnDefinition Width="150"/>
      
<ColumnDefinition Width="12"/>
      
<ColumnDefinition/>
      
      
< TextBlock  Grid.Column ="0"  Grid.Row ="0" > Red: </ TextBlock >
      <Slider Name="greenSlider" Grid.Column="1" Grid.Row="1"
              Minimum
="0" Maximum="255"              
              ValueChanged
="OnGreenSliderChanged"/>

       < TextBlock  Name ="redValue"  Grid.Column ="2"  Grid.Row ="0" />
      
      
< TextBlock  Grid.Column ="0"  Grid.Row ="1" > Green: </ TextBlock >
      
< Slider  Name ="greenSlider"  Grid.Column ="1"  Grid.Row ="1"
              Minimum
="0"  Maximum ="255"               
              ValueChanged
="OnGreenSliderChanged" />
      
< TextBlock  Name ="greenValue"  Grid.Column ="2"  Grid.Row ="1" />
      
      
< TextBlock  Grid.Column ="0"  Grid.Row ="2" > Blue: </ TextBlock >
      
< Slider  Name ="blueSlider"  Grid.Column ="1"  Grid.Row ="2"
              Minimum
="0"  Maximum ="255"               
              ValueChanged
="OnBlueSliderChanged" />
      
< TextBlock  Name ="blueValue"  Grid.Column ="2"  Grid.Row ="2" />
      
      
< Border  Grid.Column ="3"  Grid.Row ="0"  Grid.RowSpan ="3"  Margin ="5, 5, 5, 5" >
        
< Border  Name ="Preview"  BorderThickness ="1"  CornerRadius ="5"  BorderBrush ="Gray"  Background ="Black" />
      
</ Border >
    
</ Grid >
</ Window >

1. 对象
一般情况下,XML文件中的节点可以对应到一个对象或一个属性上。
各个节点之间的层次结构描述了节点之间的从属关系,例如:Window节点是这个XML的根节点,这个节点描述了一个Window对象,运行时,我们可以看到会弹出一个标准的Windows窗口出来。
这个Window对象中包含一个Grid对象,这个Grid中包含3个Slider,6个TextBlock和一个Border对象。加黄的部分是一段比较特殊的部分,后面我会专门写文章来讨论。

2. 属性
XAML中节点的属性对应到这个节点所描述对象的属性上。例如:上面的XAML中红色的部分描述了一个Slider对象,这个对象有3个属性:Minimum,Maximum,Name。Grid.Column和Grid.Row两个属性是 附加属性
如果一个XAML中的节点包含属性Name,编译器将会在代码中生成一个同名的变量引用到这个对象上。这一点,是由IDE的CodeGenerical来实现的。相关的内容,如果以后有时间,我会专门写文章来讨论IDE的CodeGenerator。

3. 事件
XAML中的事件使用和属性相同的语法来描述。例如:Slider对象的ValueChanged是一个事件。它将映射到Code中的一个方法上。

Ok, 我们现在来看一下代码怎样编写:
 1 using  System;
 2 using  System.Windows;
 3 using  System.Windows.Controls;
 4 using  System.Windows.Data;
 5 using  System.Windows.Documents;
 6 using  System.Windows.Media;
 7 using  System.Windows.Shapes;
 8
 9 namespace  Freezed
10 {
11    public partial class Window1 : Window
12    {
13        public Window1()
14        {
15            InitializeComponent();
16        }

17
18        Color _value = Colors.Black;
19
20        public void OnRedSliderChanged(Object sender, RoutedPropertyChangedEventArgs<double> e)
21        {
22            this._value = Color.FromArgb(_value.A, Convert.ToByte(e.NewValue), _value.G, _value.B);
23            this.OnValueChanged();
24        }

25        public void OnGreenSliderChanged(Object sender, RoutedPropertyChangedEventArgs<double> e)
26        {
27            this._value = Color.FromArgb(_value.A, _value.R, Convert.ToByte(e.NewValue), _value.B);
28            this.OnValueChanged();
29        }

30        public void OnBlueSliderChanged(Object sender, RoutedPropertyChangedEventArgs<double> e)
31        {
32            this._value = Color.FromArgb(_value.A, _value.R, _value.G, Convert.ToByte(e.NewValue));
33            this.OnValueChanged();
34        }

35
36        private void OnValueChanged()
37        {
38            this.Preview.Background = new SolidColorBrush(this._value);
39            this.redValue.Text = this._value.R.ToString();
40            this.greenValue.Text = this._value.G.ToString();
41            this.blueValue.Text = this._value.B.ToString();
42        }

43    }

44}
代码很简单,无非就是实现了XAML中声明调用的方法,然后同步几个对象的属性。

写到这里,发现这一章好像和“数据与表示分离”主题没有太多的关系。先作为预备知识,大家了解一下吧。因为后面的文章都会基于XAML来讨论。

XAML是WPF的核心概念之一。但是,很多人看到这里都会有这样的疑问:为什么要XAML?
微软引入XAML的一个主要的原因就是为了将界面和业务逻辑进行分离。在不远的将来,一个软件公司必须包含两类技术人才,一类是开发人员,而另一类就是设计人员。开发人员负责实现具体的业务逻辑,而设计人员仅仅进行UI的设计。他们的主要机能就是能够很好的操控XAML(与现在的WEB开发有点类似)。同时,微软正在开发新的设计器来实现可视化UI设计(花哨的就象Photoshop和CorelDraw)。

下面引用一篇老外的Blog供大家参考: If xaml is so easy, why is code so hard? 

下一篇Blog中,我们将讨论如何使用Binding实现数据与表示的分离。

本文的例子: ColorPicker1.rar
注意:本文相关的例子都在WinFX 11月CTP下测试通过,因为目前环境限制,没能再12月CTP下进行测试,请见谅。

你可能感兴趣的:(WPF)