控件

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

创建控件的实例

可以使用 Extensible Application Markup Language (XAML) 或代码将控件添加到应用程序。 下面的示例演示如何创建一个向用户询问其姓名的简单应用程序。 此示例在 XAML 中创建 6 个控件:2 个标签、2 个文本框和 2 个按钮。 所有控件均可使用相似方式创建。

<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 定义通常在 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

下面的示例为 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 内容模型

另请参阅