Элементы управления

Windows Presentation Foundation (WPF) поставляется со многими общими компонентами пользовательского интерфейса, которые используются почти во всех приложениях Windows, таких как Button, Label, TextBoxMenuи ListBox. Исторически эти объекты называются элементами управления. Хотя пакет SDK WPF продолжает использовать термин control, чтобы свободно означать любой класс, представляющий видимый объект в приложении, важно отметить, что класс не должен наследовать от Control класса, чтобы иметь видимое присутствие. Классы, наследуемые от класса Control, содержат шаблон ControlTemplate, который позволяет существенно изменить внешний вид элемента управления, не создавая новый подкласс. В этой статье описаны типичные методы применения элементов управления (которые наследуются или не наследуются от класса 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>

В следующем примере создается такое же приложение в коде. Для упрощения примера из него исключено создание Grid, grid1. 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

Изменение внешнего вида элемента управления

Обычно внешний вид элемента управления изменяется в соответствии с внешним видом приложения. Можно изменить внешний вид элемента управления, выполнив одно из следующих действий (в зависимости от того, чего нужно достичь):

  • Измените значение свойства элемента управления.

  • Создайте Style для элемента управления.

  • Создайте новый ControlTemplate для элемента управления.

Изменение значения свойства элемента управления

У многих элементов управления есть свойства, которые позволяют изменять внешний вид элемента управления, например, Background для Button. Значения свойства можно задать как на XAML, так и в коде. В следующем примере устанавливаются свойства Background, FontSize и FontWeight для Button на XAML.

<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, который применяется к каждому объекту Button в приложении. Определения Style обычно задаются на XAML в ResourceDictionary, например свойство Resources объекта FrameworkElement.

<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 элемента управления. Дополнительные сведения о стилях см. в статье Стили и шаблоны в WPF.

Создание ControlTemplate

Style позволяет задать свойства для нескольких элементов управления одновременно, но иногда для настройки внешнего вида Control вам потребуется больше возможностей, чем предоставляет создание Style. Классы, которые наследуются от класса Control, имеют ControlTemplate, который определяет структуру и внешний вид Control. Свойство Template для Control является открытым, поэтому пользователь может указать для Control значение ControlTemplate, отличное от значения по умолчанию. Обычно для настройки внешнего вида Control можно указать новый ControlTemplate для Control, а не наследовать свойства элемента управления.

Давайте рассмотрим очень популярный элемент управления Button. Основное назначение Button — предоставить приложению возможность выполнить определенное действие, когда пользователь нажимает кнопку. По умолчанию Button в WPF отображается как объемный прямоугольник. При разработке приложения вас обычно интересует поведение Button, то есть обработка события нажатия кнопки, но вы можете изменить еще и внешний вид кнопки, не ограничиваясь стандартными свойствами кнопки. В нашем примере создается новый ControlTemplate.

В следующем примере создается ControlTemplate для Button. ControlTemplate создает Button со скругленными углами и градиентным фоном. ControlTemplate содержит Border, у которого Background является LinearGradientBrush с двумя объектами GradientStop. Первый GradientStop использует привязку данных, чтобы связать свойство Color объекта GradientStop с цветом фона кнопки. Когда вы изменяете свойство Background объекта Button, соответствующий новому значению цвет будет использоваться как первый GradientStop. Дополнительные сведения о привязке данных см. в разделе Общие сведения о привязке данных. Также в этом примере создается Trigger, который изменяет внешний вид Button, если IsPressed имеет значение true.

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

Примечание.

Чтобы наш пример работал правильно, свойство Background для Button должно иметь значение SolidColorBrush.

Подписка на события

Можно подписаться на событие элемента управления с помощью XAML или кода, но обрабатывать события можно только в коде. Следующий пример демонстрирует, как подписаться на событие Click объекта Button.

<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

Следующий пример демонстрирует, как обрабатывать событие Click объекта Button.

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 может содержать любой объект, Image или Panel. Следующие классы обеспечивают поддержку форматированного содержимого и служат базовыми классами для большинства элементов управления в WPF.

  • ContentControl — в качестве примеров классов, которые наследуются от этого класса, можно назвать Label, Button, и ToolTip.

  • ItemsControl — в качестве примеров классов, которые наследуются от этого класса, можно назвать ListBox, Menu, и StatusBar.

  • HeaderedContentControl — в качестве примеров классов, которые наследуются от этого класса, можно назвать TabItem, GroupBox, и Expander.

  • HeaderedItemsControl — в качестве примеров классов, которые наследуются от этого класса, можно назвать MenuItem, TreeViewItem, и ToolBar.

Для получения дополнительной информации об этих базовых классах см. раздел Модель содержимого WPF.

См. также