控件

Windows Presentation Foundation (WPF) 附带了许多几乎在所有 Windows 应用程序中都会使用的常见 UI 组件,如 ButtonLabelTextBoxMenuListBox。 以前,这些对象被称为控件。 现在,WPF SDK 继续使用术语“控件”泛指任何代表应用程序中可见对象的类。请注意,类不必从 Control 类继承即可具有可见外观。 从 Control 类继承的类包含一个 ControlTemplate,允许控件的使用方在无需创建新子类的情况下根本改变控件的外观。 本主题讨论在 WPF 中使用控件(包括从 Control 类继承的控件以及不从该类继承的控件)的常见方式。

本主题包括下列各节。

  • 创建控件的实例
  • 更改控件外观
  • 订阅事件
  • 控件中的丰富内容
  • 相关主题

创建控件的实例

可以通过使用Extensible Application Markup Language (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>

下面的示例以代码的形式创建同一应用程序。 为简洁起见,示例中省略了 Grid grid1 的创建过程。 grid1 的列和行定义与前面的 XAML 示例中所示的相同。

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 'CreateControls
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);

}

更改控件外观

更改控件的外观以适应应用程序的外观,这是很常见的操作。 可以根据您要达到的效果,通过执行以下操作之一来更改控件的外观:

更改控件的属性值

许多控件具有允许您更改控件外观的属性,例如 ButtonBackground。 可以在 XAML 和代码中设置值属性。 下面的示例在 XAML 中设置 ButtonBackgroundFontSizeFontWeight 属性。

<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>

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

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
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;

为控件创建样式

利用 WPF,通过创建 Style,您可以同时为许多控件指定相同的外观,而不是在应用程序中设置每个实例的属性。 下面的示例创建一个 Style,它可以应用于应用程序中的每个 ButtonStyle 定义通常是在 ResourceDictionary(例如 FrameworkElementResources 属性)中以 XAML 形式定义的。

<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 属性中指定该键,还可将样式仅应用于某些特定类型的控件。 有关样式的更多信息,请参见样式设置和模板化

创建 ControlTemplate

利用 Style,可以一次为多个控件设置属性,但有时除了通过创建 Style 可执行的操作之外,您可能想要自定义 Control 的外观。 从 Control 类继承的类具有 ControlTemplate,它用于定义 Control 的结构和外观。 ControlTemplate 属性是公共的,因此您可以为 Control 指定非默认 ControlTemplate。 通常,您可以为 Control 指定新的 ControlTemplate(而不是从控件继承)以自定义 Control 的外观。

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

下面的示例创建 ButtonControlTemplateControlTemplate 创建一个带圆角和渐变背景的 ButtonControlTemplate 包含一个 Border,其 BackgroundLinearGradientBrush,它具有两个 GradientStop 对象。 第一个 GradientStop 使用数据绑定将 GradientStopColor 属性绑定到按钮背景的颜色。 当设置 ButtonBackground 属性时,该值的颜色将用作第一个 GradientStop。 有关数据绑定的更多信息,请参见 数据绑定概述。 此示例还创建一个 Trigger,用于在 IsPressed 为 true 时更改 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 或代码来订阅控件的事件,但只能在代码中处理事件。 下面的示例演示如何订阅 Button 的 Click 事件。

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

下面的示例处理 Button 的 Click 事件。

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

End Sub 'submit_Click
void submit_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
}

控件中的丰富内容

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

有关这些基类的更多信息,请参见 WPF 内容模型

请参见

任务

如何:启用命令

参考

按类别分类的控件

概念

样式设置和模板化

数据模板化概述

数据绑定概述

其他资源

控件库

输入和命令

演练:创建自定义的动画按钮

控件自定义