控件

Windows Presentation Foundation(WPF)附带了几乎所有 Windows 应用程序中使用的常见 UI 组件,例如 ButtonLabelTextBoxMenuListBox。 从历史上看,这些对象被称为控件。 虽然 WPF SDK 继续使用术语“control”松散表示应用程序中可见对象的任何类,但请务必注意,类不需要继承自 Control 类才能有可见状态。 继承自 Control 类的类包含一个 ControlTemplate,它允许控件使用者从根本上更改控件的外观,而无需创建新的子类。 本主题讨论控件(包括继承自 Control 类的控件和未继承自 Control 类的控件)通常如何用于 WPF。

创建控件的实例

可以使用可扩展应用程序标记语言(XAML)或代码将控件添加到应用程序。 以下示例演示如何创建一个简单的应用程序,要求用户输入其名字和姓氏。 此示例在 XAML 中创建六个控件:两个标签、两个文本框和两个按钮。 可以类似地创建所有控件。

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="30"/>
    <RowDefinition Height="30"/>
    <RowDefinition Height="30"/>
    <RowDefinition/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition/>
    <ColumnDefinition/>
  </Grid.ColumnDefinitions>

  <Label>
    Enter your first name:
  </Label>
  <TextBox Grid.Row="0" Grid.Column="1" 
           Name="firstName" Margin="0,5,10,5"/>

  <Label Grid.Row="1" >
    Enter your last name:
  </Label>
  <TextBox Grid.Row="1" Grid.Column="1" 
           Name="lastName" Margin="0,5,10,5"/>

  <Button Grid.Row="2" Grid.Column="0" 
          Name="submit" Margin="2">
    View message
  </Button>

  <Button Grid.Row="2" Grid.Column="1" 
          Name="Clear" Margin="2">
    Clear Name
  </Button>
</Grid>

以下示例在代码中创建相同的应用程序。 为简洁起见,示例中省略了 Gridgrid1 的创建过程。 grid1 具有相同的列和行定义,如前面的 XAML 示例所示。

Label firstNameLabel;
Label lastNameLabel;
TextBox firstName;
TextBox lastName;
Button submit;
Button clear;

void CreateControls()
{
    firstNameLabel = new Label();
    firstNameLabel.Content = "Enter your first name:";
    grid1.Children.Add(firstNameLabel);

    firstName = new TextBox();
    firstName.Margin = new Thickness(0, 5, 10, 5);
    Grid.SetColumn(firstName, 1);
    grid1.Children.Add(firstName);

    lastNameLabel = new Label();
    lastNameLabel.Content = "Enter your last name:";
    Grid.SetRow(lastNameLabel, 1);
    grid1.Children.Add(lastNameLabel);

    lastName = new TextBox();
    lastName.Margin = new Thickness(0, 5, 10, 5);
    Grid.SetColumn(lastName, 1);
    Grid.SetRow(lastName, 1);
    grid1.Children.Add(lastName);

    submit = new Button();
    submit.Content = "View message";
    Grid.SetRow(submit, 2);
    grid1.Children.Add(submit);

    clear = new Button();
    clear.Content = "Clear Name";
    Grid.SetRow(clear, 2);
    Grid.SetColumn(clear, 1);
    grid1.Children.Add(clear);
}
Private firstNameLabel As Label
Private lastNameLabel As Label
Private firstName As TextBox
Private lastName As TextBox
Private submit As Button
Private clear As Button

Sub CreateControls()
    firstNameLabel = New Label()
    firstNameLabel.Content = "Enter your first name:"
    grid1.Children.Add(firstNameLabel)

    firstName = New TextBox()
    firstName.Margin = New Thickness(0, 5, 10, 5)
    Grid.SetColumn(firstName, 1)
    grid1.Children.Add(firstName)

    lastNameLabel = New Label()
    lastNameLabel.Content = "Enter your last name:"
    Grid.SetRow(lastNameLabel, 1)
    grid1.Children.Add(lastNameLabel)

    lastName = New TextBox()
    lastName.Margin = New Thickness(0, 5, 10, 5)
    Grid.SetColumn(lastName, 1)
    Grid.SetRow(lastName, 1)
    grid1.Children.Add(lastName)

    submit = New Button()
    submit.Content = "View message"
    Grid.SetRow(submit, 2)
    grid1.Children.Add(submit)

    clear = New Button()
    clear.Content = "Clear Name"
    Grid.SetRow(clear, 2)
    Grid.SetColumn(clear, 1)
    grid1.Children.Add(clear)


End Sub

更改控件的外观

通常更改控件的外观以适应应用程序的外观。 可以通过执行以下操作之一来更改控件的外观,具体取决于要完成的内容:

更改控件的属性值

许多控件都有一些属性,可用于更改控件的显示方式,例如 ButtonBackground。 可以在 XAML 和代码中设置值属性。 以下示例设置 XAML 中 Button 上的 BackgroundFontSizeFontWeight 属性。

<Button FontSize="14" FontWeight="Bold">
  <!--Set the Background property of the Button to
    a LinearGradientBrush.-->
  <Button.Background>
    <LinearGradientBrush StartPoint="0,0.5" 
                            EndPoint="1,0.5">
      <GradientStop Color="Green" Offset="0.0" />
      <GradientStop Color="White" Offset="0.9" />
    </LinearGradientBrush>

  </Button.Background>
  View message
</Button>

以下示例在代码中设置相同的属性。

LinearGradientBrush buttonBrush = new LinearGradientBrush();
buttonBrush.StartPoint = new Point(0, 0.5);
buttonBrush.EndPoint = new Point(1, 0.5);
buttonBrush.GradientStops.Add(new GradientStop(Colors.Green, 0));
buttonBrush.GradientStops.Add(new GradientStop(Colors.White, 0.9));

submit.Background = buttonBrush;
submit.FontSize = 14;
submit.FontWeight = FontWeights.Bold;
Dim buttonBrush As New LinearGradientBrush()
buttonBrush.StartPoint = New Point(0, 0.5)
buttonBrush.EndPoint = New Point(1, 0.5)
buttonBrush.GradientStops.Add(New GradientStop(Colors.Green, 0))
buttonBrush.GradientStops.Add(New GradientStop(Colors.White, 0.9))

submit.Background = buttonBrush
submit.FontSize = 14
submit.FontWeight = FontWeights.Bold

为控件创建样式

WPF 使你可以通过创建 Style来指定控件的整体外观,而不是为应用程序中的每个实例单独设置属性。 下面的示例创建一个 Style,它将应用于应用程序中的每个 ButtonStyle 定义通常在 XAML 中的 ResourceDictionary中定义,例如 FrameworkElementResources 属性。

<Style TargetType="Button">
  <Setter Property="FontSize" Value="14"/>
  <Setter Property="FontWeight" Value="Bold"/>
  <Setter Property="Background">
    <Setter.Value>
      <LinearGradientBrush StartPoint="0,0.5" 
                              EndPoint="1,0.5">
        <GradientStop Color="Green" Offset="0.0" />
        <GradientStop Color="White" Offset="0.9" />
      </LinearGradientBrush>

    </Setter.Value>
  </Setter>
</Style>

您还可以通过将一个键分配给该样式并在控件的 Style 属性中指定该键,来将样式应用于特定类型的某些控件。 有关样式的详细信息,请参阅 样式和模板化

创建控制模板

Style 允许您一次设置多个控件的属性,但有时您可能希望自定义 Control 的外观,超出通过创建 Style所能实现的范围。 继承自 Control 类的类具有 ControlTemplate,用于定义 Control的结构和外观。 ControlTemplate 属性是公共的,所以你可以将一个不同于其默认值的 ControlTemplate 赋给 Control。 通常可以为 Control 指定新的 ControlTemplate(而不是从控件继承)以自定义 Control 的外观。

请考虑一个很常用的控件 ButtonButton 的主要行为是让用户在单击应用程序时执行某些操作。 默认情况下,WPF 中的 Button 显示为凸起的矩形。 开发应用程序时,用户可能希望利用 Button 的行为(即通过处理按钮的单击事件),不过,除了通过更改按钮的属性可以执行的操作外,也可以更改按钮的外观。 在这种情况下,可以创建新的 ControlTemplate

下面的示例为 Button 创建了一个 ControlTemplateControlTemplate 创建一个带圆角和渐变背景的 ButtonControlTemplate 包含一个 Border,其 Background 是带有两个 GradientStop 对象的 LinearGradientBrush。 第一个 GradientStop 使用数据绑定将 GradientStopColor 属性绑定到按钮背景的颜色。 设置 ButtonBackground 属性时,该值的颜色将用作第一个 GradientStop。 有关数据绑定的详细信息,请参阅 数据绑定概述。 此示例还创建一个 Trigger,用于在 IsPressedtrue 时更改 Button 的外观。

<!--Define a template that creates a gradient-colored button.-->
<Style TargetType="Button">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Border 
          x:Name="Border"  
          CornerRadius="20" 
          BorderThickness="1"
          BorderBrush="Black">
          <Border.Background>
            <LinearGradientBrush StartPoint="0,0.5" 
                                 EndPoint="1,0.5">
              <GradientStop Color="{Binding Background.Color, 
                    RelativeSource={RelativeSource TemplatedParent}}" 
                            Offset="0.0" />
              <GradientStop Color="White" Offset="0.9" />
            </LinearGradientBrush>
          </Border.Background>
          <ContentPresenter 
            Margin="2"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            RecognizesAccessKey="True"/>
        </Border>
        <ControlTemplate.Triggers>
          <!--Change the appearance of
          the button when the user clicks it.-->
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background">
              <Setter.Value>
                <LinearGradientBrush StartPoint="0,0.5" 
                                     EndPoint="1,0.5">
                  <GradientStop Color="{Binding Background.Color, 
                    RelativeSource={RelativeSource TemplatedParent}}" 
                                Offset="0.0" />
                  <GradientStop Color="DarkSlateGray" Offset="0.9" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
          </Trigger>

        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName"
        Background="Green">View message</Button>

说明

ButtonBackground 属性必须设置为 SolidColorBrush,才能使示例正常工作。

订阅事件通知

可以使用 XAML 或代码来订阅控件的事件,但只能在代码中处理事件。 下面的示例演示如何订阅 ButtonClick 事件。

<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName" Click="submit_Click"
  Background="Green">View message</Button>
submit.Click += new RoutedEventHandler(submit_Click);
AddHandler submit.Click, AddressOf submit_Click

下面的示例处理 ButtonClick 事件。

void submit_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
}
Private Sub submit_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text)

End Sub

控件中的丰富内容

Control 类继承的大多数类具有承载丰富内容的能力。 例如,Label 可以包含任何对象,例如字符串、ImagePanel。 以下类支持丰富的内容,并充当 WPF 中大多数控件的基类。

有关这些基类的详细信息,请参阅 WPF 内容模型

另请参阅