三、事件处理程序与代码隐藏

例如,为一个Page添加一个Button控件,并为该Button添加事件名称Button_Click:

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="ExampleNamespace.ExamplePage">
  <Button Click="Button_Click" >Click Me!</Button>
</Page>
然后为该Button的事件处理程序添加实现代码:
namespace ExampleNamespace
{
  public partial class ExamplePage
  {
    void Button_Click(object sender, RoutedEventArgs e)
    {
      Button b = e.Source as Button;
      b.Foreground = Brushes.Red;
    }
  }
}

于是,这样就把Button连接到事件处理程序Button_Click。

四、命名元素

例如,在XAML文件中,为Grid命名为grid1:

<Grid x:Name="grid1">
</Grid>

或者,在VS的设计窗口中,设置Grid元素属性,将名称属性改为grid1。

现在,可以在C#代码中使用grid1了:

MessageBox.Show(String.Format("The grid is {0}x{1} units in size.",
grid1.ActualWidth, grid1.ActualHeight));

注意,与WinForm不同,WPF的控件不必每个都为之命名。

五、附加属性与附加事件——一个WPF例子

借用书中EightBalls的例子,其中UI如下:

image

在上面的TextBox输入问题,然后点击按钮,程序在下面的TextBox输出答案。

<Window x:Class="EightBall.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Eight Ball Answer" Height="328" Width="412" >
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.Background>
      <LinearGradientBrush>
        <LinearGradientBrush.GradientStops>
          <GradientStop Offset="0.00"  Color="Red" />
          <GradientStop Offset="0.50" Color="Indigo" />
          <GradientStop Offset="1.00" Color="Violet" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Grid.Background>
    <TextBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="10,10,13,10" Name="txtQuestion" 
             TextWrapping="Wrap" FontFamily="Verdana" FontSize="24"
             Grid.Row="0" >
      [Place question here.]
    </TextBox>
    <Button VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,0,0,20" Width="127" Height="23" Name="cmdAnswer"
            Click="cmdAnswer_Click" 
            Grid.Row="1">      
      Ask the Eight Ball
      </Button>
    <TextBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="10,10,13,10" Name="txtAnswer" 
             TextWrapping="Wrap" IsReadOnly="True" FontFamily="Verdana" FontSize="24" Foreground="Green"
             Grid.Row="2">
      [Answer will appear here.]
    </TextBox>          
  </Grid>
</Window>

C#实现代码:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Input;

namespace EightBall
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>

    public partial class Window1 : Window
    {

        public Window1()
        {
            InitializeComponent();
        }

        private void cmdAnswer_Click(object sender, RoutedEventArgs e)
        {           
            // Dramatic delay...
            this.Cursor = Cursors.Wait;
            System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));

            AnswerGenerator generator = new AnswerGenerator();
            txtAnswer.Text = generator.GetRandomAnswer(txtQuestion.Text);
            this.Cursor = null;
        }

    }
}

1.XAML指定一个语言功能,该功能的属性版本称为附加属性,事件版本称为附加事件。 从概念上讲,可以将附加属性和附加事件视为可以在任何 XAML 元素/对象实例上设置的全局成员。 但是,元素/类或更大的基础结构必须支持附加值的后备属性存储。在特性语法中,您可以采用“所有者类型.属性名”的形式指定附加属性。

2.在Grid.Property嵌套LinerGridientBrush,再嵌套LinearGradientBrush.GradientStops,并对此设置属性。

3.标记扩展:x:Type,x:Static,x:Array,x:Null。语法:{MarkupExtensionClass Argument}。

标记扩展继承自基类System.Windows.Markup.MarkupExtention。例如,

<Button ... Foreground="{x:Static SystemColors.ActiveCaptionBrush}" >

这等同于将标记扩展嵌套到对象属性:

<Button ... >
<Button.Foreground>
<x:Static Member="SystemColors.ActiveCaptionBrush"></x:Static>
</Button.Foreground>
</Button>

4.附加属性:通常用于容器中的控件。每个控件都有其固有的附加属性,取决于它所在的容器。例如:

<TextBox Grid.Row=”0”>
</TextBox>
<Button Grid.Row=”1”>
Ask the Eight Ball
</Button>
<TextBox Grid.Row=”2”>
</TextBox>

附加属性不是真正的属性,它们被转换成方法调用:DefiningType.SetPropertyName()。如上代码,会被转换成:

Grid.SetRow().
Grid.SetRow(txtQuestion, 0);

5.嵌套元素:Window包含Grid,Grid包含TextBox和Button。

IList.Add();

IDictionary.Add();

ContentProperty:

例如,

<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="Red" />
<GradientStop Offset="0.50" Color="Indigo" />
<GradientStop Offset="1.00" Color="Violet" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>

GradientStops属性返回一个GradientStopCollection对象,而GradientStopCollection实现IList接口。因此,每个GradientStop调用IList.Add()方法。

上述XAML代码等同于:

GradientStop gradientStop1 = new GradientStop();
gradientStop1.Offset = 0;
gradientStop1.Color = Colors.Red;
IList list = brush.GradientStops;
list.Add(gradientStop1);

6.Collection。某些属性可能支持不止一种Collection。因此,要添加标签指定Collection类:

<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.00" Color="Red" />
<GradientStop Offset="0.50" Color="Indigo" />
<GradientStop Offset="1.00" Color="Violet" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>