科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件XAML开发入门之XAML的五大元素

XAML开发入门之XAML的五大元素

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

所有的XAML均是一个WPF类,但是并不是所有的WPF类都可以用XAML描述

作者:轩辕南宫 来源:天极开发 2007年11月3日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
属性

  在本文曾多次提过XAML元素的属性是和WPF类中的属性对应的,例如XAML中的Button元素存在Width属性,该属性是和System.Windows.Button类中的Width属性对应的。为了说明XAML和WPF类的相互关系,我们分别在如下的两个程序清单中使用XAML和C#来声明一个Button元素实例:

36 <Button
37 Width="100"
38 Name="myButton"
39 Height="20"
40 Content="This is my button" />

  相应的C#代码实现:

41 Button myButton;
42 myButton.Width=100;
43 myButton.Height=20;
44 myButton.Content = "This is my button";

  就如同XAML中的Button元素名称和Button类的名称相同一样,Button元素的各个属性也和Button类中的属性名称一一对应(Name= Name,Height=Height,依此类推)。

  在上述代码示例中,Name和Content属性的类型都是String,因为XML本身就是一种基于文本的格式,所以其属性值用文本来描述是合乎情理的。那么作为XML的一种衍生类型,XAML其属性是否还有其它类型呢?我们在下面的示例代码使用了不同的属性类型:

45 <Rectangle
46 Width="200"
47 Height="100"
48 Stroke="Red"
49 Fill="Yellow" />

  在上述的Rectangle元素中没有一个属性是String类型的,Width和Height都是Double类型的,而Stroke和Fill是Brush类型的。为了支持各自不同的属性类型,XAML需要使用.NET中的类型转换系统(TypeConverter)。也就是在XAML中的所有属性值都是用文本字符串来描述的,但是类型转换系统会在某一特定的阶段将这些文本字符串和属性本身的类型映射起来。例如在上述的示例中,LengthConverter类型转换器会自动将Width和Height对应的"200"和"100"文本字符串转换为双精度类型的200和100(WPF之所以知道使用Double类型是因为在FrameworkElement类中的WidthProperty和HeightProperty字段被标记了一个TypeConverterAttribute,这样就可以知道在类型转换时使用何种类型转换器)。由于Stroke和Fill这两个属性并没有标记一个TypeConverterAttribute,但是它们都是属性Brush类型的,而Brush类型又标记一个TypeConverterAttribute来指定其类型转换器为BrushConverter,所以BrushConverter会自动将其文本字符串类型的属性值转换为Brush类型。

  尽管WPF中的类型转换系统是非常有用的,但是在某些情况下它仍然存在着一些不足。例如某个属性值不存在适合的类型转换器进行从文本到实际类型的转换,或者是一个描述属性值的文本字符串过于复杂,以致我们不得不作大量的工作才可以实现类型的转换。现在请你考虑一个问题,我们要实现上述的给矩形填充一种颜色是非常容易的,但是如果我们要给一个矩形填充多种颜色该怎么实现呢(具体的效果见3-3)?我们不可以像上面那样直接使用Fill="Yellow Red…"这样的方式去为矩形设置不同的颜色,也就是说BrushConverter类型转换器是无法直接转换这种包含多个颜色描述文本的字符串的。为了讲解上述类型转换系统的缺点,这里引入了一个新的概念,那就是从属属性。


图3-3 带渐变效果的Button元素

  这里先使用一个简单的实例来说明下什么是从属属性,从属属性就是一种"属性-元素"的语法,使用这种语法来设置一个属性时,你可以使用一种嵌套方式的元素替代原本要设置的属性。这个嵌套方式的元素其格式为"父元素.属性名",这里的父元素就是将要设置属性的元素,而属性名就是对应的在元素中要设置的属性。这里说的可能让你有点糊涂,没关系,现在我们看看下面的程序清单:

01 <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
02 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
03 <Button Width="200" Height="100">
04 <Button.Background>
05 <SolidColorBrush Color="Blue" />
06 </Button.Background>
07 Click me
08 </Button>
09 </Page>

  这是对应的C#实现代码:

01 Button btn = new Button( );
02 SolidColorBrush brush = new SolidColorBrush( );
03 brush.Color = Colors.Blue;
04 btn.Background = brush;
05 btn.AddText("Click me");


  我们要为Button预算设置其背景颜色为蓝色。在上面的示例中我们使用了从属属性"父元素.属性名"类型的语法,其中第4行的<Button.Background>就是一个从属属性,它以元素的形式存在,但是其实质上却是一个属性。

  上面仅仅是为了让你了解从属属性的用法和实现方式,如果只是为了实现上述的效果,那么下面的程序清单完全就可以实现,你只需将Background设置为"Blue"就行了完全没有必要大费周章地使用从属属性。尽管使用"父元素.属性名"这样格式的从属属性去设置一个背景颜色显得很复杂,但是这种版本的实现可以清楚地看到你在这所创建的是何种类型的brush。

01 <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
02 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
03 <Button
04 Width="200"
05 Height="100"
06 Background="Blue">
07 </Button>
08 </Page>

  如果使用从属属性只是为了了解底层的类型转换实现机制的话,那么我们根本就没有理由去使用这些冗长的语法实现。从属属性之所以重要是因为在某些情况下我们需要在一个属性中实现非常复杂的定义,就如同我们上述提及的要在一个矩形中使用多种颜色作背景。其代码如下:

01 <Button VerticalAlignment="Center" HorizontalAlignment="Center">
02 <Button.Background>
03 <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
04 <LinearGradientBrush.GradientStops>
05 <GradientStop Offset="0" Color="Yellow" />
06 <GradientStop Offset="0.35" Color="Red" />
07 <GradientStop Offset="1" Color="Green" />
08 </LinearGradientBrush.GradientStops>
09 </LinearGradientBrush>
10 </Button.Background>
11 Click me
12 </Button>

  这是使用C#实现的对应版本

01 Button b = new Button( );
02 b.VerticalAlignment = VerticalAlignment.Center;
03 b.HorizontalAlignment = HorizontalAlignment.Center;
04 LinearGradientBrush brush = new LinearGradientBrush( );
05 brush.StartPoint = new Point(0,0);
06 brush.EndPoint = new Point(0,1);
07 GradientStop gs = new GradientStop( );
08 gs.Offset = 0;
09 gs.Color = Color.FromRgb(0x80, 0, 0);
10 brush.GradientStops.AddChild(gs);
11 gs = new GradientStop( );
12 gs.Offset = 0.35;
13 gs.Color = Colors.Red;
14 brush.GradientStops.AddChild(gs);
15 gs = new GradientStop( );
16 gs.Offset = 0.35;
17 gs.Color = Color.FromRgb(0x50, 0, 0);
18 brush.GradientStops.AddChild(gs);
19 b.Background = brush;
20 b.AddText("Click me");

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章