Kontrolki

Program Windows Presentation Foundation (WPF) jest dostarczany z wieloma typowymi składnikami interfejsu użytkownika, które są używane w prawie każdej aplikacji systemu Windows, takich jak Button, , LabelTextBox, Menu, i ListBox. W przeszłości te obiekty były określane jako kontrolki. Zestaw SDK WPF nadal używa terminu "control", aby luźno oznaczać dowolną klasę reprezentującą widoczny obiekt w aplikacji, należy pamiętać, że klasa nie musi dziedziczyć z Control klasy, aby mieć widoczną obecność. Klasy dziedziczące z klasy Control zawierają klasę ControlTemplate, która umożliwia użytkownikowi kontrolki radykalną zmianę wyglądu kontrolki bez konieczności tworzenia nowej podklasy. W tym temacie omówiono, w jaki sposób kontrolki (zarówno te, które dziedziczą z klasy Control, jak i te, które nie dziedziczą) są często używane w strukturze WPF.

Tworzenie wystąpienia kontrolki

Kontrolkę można dodać do aplikacji przy użyciu języka XAML (Extensible Application Markup Language) lub kodu. W poniższym przykładzie pokazano, jak utworzyć prostą aplikację, która prosi użytkownika o imię i nazwisko. W tym przykładzie utworzono sześć kontrolek: dwie etykiety, dwa pola tekstowe i dwa przyciski w języku XAML. Wszystkie kontrolki można utworzyć w podobny sposób.

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

Poniższy przykład przedstawia tworzenie tej samej aplikacji w kodzie. Dla większej zwięzłości tworzenie elementu Grid, grid1, nie znalazło się w przykładzie. Element grid1 zawiera takie same definicje kolumn i wierszy, jak pokazano w poprzednim przykładzie 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

Zmiana wyglądu kontrolki

Wygląd kontrolki często zmienia się tak, aby pasował do wyglądu i sposobu działania aplikacji. Wygląd kontrolki można zmienić, wykonując jedną z następujących czynności, w zależności od tego, co chcesz uzyskać:

  • Zmień wartość właściwości kontrolki.

  • Utwórz element Style dla kontrolki.

  • Utwórz nowy element ControlTemplate dla kontrolki.

Zmiana wartości właściwości kontrolki

Wiele kontrolek ma właściwości, które umożliwiają zmianę sposobu wyświetlania kontrolki, na przykład elementu Background z Button. Właściwości wartości można ustawić zarówno w języku XAML, jak i w kodzie. Poniższy przekład przedstawia ustawienie właściwości Background, FontSize i FontWeight na elemencie Button w języku 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>

Poniższy przykład przedstawia ustawienie tych samych właściwości w kodzie.

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

Tworzenie stylu dla kontrolki

Struktura WPF umożliwia określenie wyglądu kontrolek hurtowo, zamiast ustawiania właściwości dla każdego wystąpienia w aplikacji przez utworzenie elementu Style. Poniższy przykład przedstawia tworzenie elementu Style, który jest stosowany do każdej kontrolki Button w aplikacji. Definicje Style zazwyczaj są określane w języku XAML w elemencie ResourceDictionary, na przykład właściwość Resources elementu 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>

Styl można również zastosować tylko do niektórych kontrolek określonego typu, przypisując klucz do stylu i określając ten klucz we właściwości Style kontrolki. Aby uzyskać więcej informacji na temat stylów, zobacz Tworzenie stylów i tworzenie szablonów.

Tworzenie elementu ControlTemplate

Element Style umożliwia ustawienie właściwości dla wielu kontrolek jednocześnie, ale czasami może być potrzebne dostosowanie wyglądu elementu Control bardziej niż w przypadku tworzenia elementu Style. Klasy dziedziczące z klasy Control mają klasę ControlTemplate, która definiuje strukturę i wygląd elementu Control. Właściwość Template elementu Control jest publiczna, dzięki czemu można nadać wartość ControlControlTemplate inną niż domyślna. Często można określić nową właściwość ControlTemplate dla elementu Control, zamiast dziedziczyć ją z kontrolki w celu dostosowania wyglądu elementu Control.

Weźmy pod uwagę bardzo popularną kontrolkę Button. Podstawowym zachowaniem kontrolki Button jest umożliwienie aplikacji podjęcia pewnych działań po kliknięciu jej przez użytkownika. Domyślnie kontrolka Button w strukturze WPF jest wyświetlana jako wypukły prostokąt. Podczas tworzenia aplikacji możesz chcieć skorzystać z zachowania elementu Button — czyli obsługi zdarzenia kliknięcia przycisku — ale zmienić wygląd przycisku bardziej niż przez zmianę właściwości przycisku. W takim przypadku możesz utworzyć nowy element ControlTemplate.

Poniższy przykład przedstawia tworzenie właściwości ControlTemplate dla elementu Button. Element ControlTemplate tworzy kontrolkę Button z zaokrąglonymi rogami i tłem gradientowym. ControlTemplate zawiera element Border, której kontrolka Background jest elementem LinearGradientBrush z dwoma obiektami GradientStop. Pierwszy obiekt GradientStop używa powiązania danych, aby powiązać właściwość Color elementu GradientStop z kolorem tła przycisku. Po ustawieniu właściwości Background elementu Button kolor o tej wartości będzie używany jako pierwszy obiekt GradientStop. Aby uzyskać więcej informacji na temat tworzenia powiązań danych, zobacz Omówienie powiązań danych. Przykład przedstawia również tworzenie elementu Trigger, który zmienia wygląd obiektu Button, gdy właściwość IsPressed ma wartość 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>

Uwaga

Właściwość Background obiektu Button musi być ustawiona na wartość SolidColorBrush, aby przykład działał prawidłowo.

Subskrybowanie zdarzeń

Zdarzenie kontrolki można subskrybować przy użyciu języka XAML lub kodu, ale zdarzenie można obsługiwać tylko w kodzie. W poniższym przykładzie pokazano, jak zasubskrybować zdarzenie Click kontrolki 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

Poniższy przykład przedstawia obsługę zdarzenia Click kontrolki 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

Zaawansowana zawartość w kontrolkach

Większość klas dziedziczących z klasy Control może przechowywać zaawansowaną zawartość. Na przykład element Label może zawierać dowolny obiekt, taki jak ciąg, Image lub Panel. Poniższe klasy zapewniają obsługę zaawansowanej zawartości i działają jako klasy bazowe dla większości kontrolek w strukturze WPF.

Aby uzyskać więcej informacji na temat tych klas bazowych, zobacz Model zawartości WPF.

Zobacz też