Ovládací prvky

Windows Presentation Foundation (WPF) se dodává s mnoha běžnými komponentami uživatelského rozhraní, které se používají téměř ve všech aplikacích systému Windows, například Button, , LabelTextBox, Menua ListBox. Tyto objekty byly historicky označovány jako ovládací prvky. Zatímco WPF SDK nadále používá termín "control" volně znamenat všechny třídy, které představují viditelný objekt v aplikaci, je důležité si uvědomit, že třída nemusí dědit z Control třídy, aby měla viditelné přítomnost. Třídy, které dědí z třídy Control, obsahují ControlTemplate, díky čemuž může uživatel ovládacího prvku značně změnit jeho vzhled, aniž by bylo nutné vytvářet novou podtřídu. Toto téma popisuje, jak se ovládací prvky (jak ty, které dědí z třídy Control, tak ty, které z ní nedědí) běžně používají ve WPF.

Vytvoření instance ovládacího prvku

Ovládací prvek můžete do aplikace přidat pomocí jazyka XAML (Extensible Application Markup Language) nebo kódu. Následující příklad ukazuje, jak vytvořit jednoduchou aplikaci, která uživatele požádá o křestní jméno a příjmení. Tento příklad vytvoří šest ovládacích prvků: dva popisky, dvě textová pole a dvě tlačítka v XAML. Všechny ovládací prvky je možné vytvářet podobným způsobem.

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

Následující příklad vytvoří aplikaci se stejným kódem. Pro stručnost tato ukázka neobsahuje vytvoření Grid a grid1. grid1 má stejné definice sloupce a řádku, jaké měl předchozí příklad 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

Změna vzhledu ovládacího prvku

Často se vzhled ovládacího prvku mění tak, aby odpovídal vzhledu a chování aplikace. Podle toho, čeho přesně chcete dosáhnout, je možné vzhled ovládacího prvku změnit jedním z následujících postupů:

  • Změnou hodnoty vlastnosti ovládacího prvku

  • Vytvořením Style pro ovládací prvek

  • Vytvořením nového ControlTemplate pro ovládací prvek

Změna hodnoty vlastnosti ovládacího prvku

Mnoho ovládacích prvků má vlastnosti, které umožňují změnit jejich vzhled, třeba Background nebo Button. Vlastnosti s hodnotou můžete nastavovat v XAML i v kódu. Následující příklad nastavuje vlastnosti Background, FontSize a FontWeight pro Button v 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>

Následující příklad nastavuje stejné vlastnosti v kódu.

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

Vytvoření stylu pro ovládací prvek

WPF nabízí možnost hromadně nastavovat vzhled ovládacích prvků, není nutné nastavovat vlastnosti pro každou instanci v aplikaci. Stačí vytvořit Style. Následující příklad vytvoří Style, které se zavede pro všechny Button v aplikaci. Definice Style se obvykle provádějí v XAML v ResourceDictionary, například ve vlastnosti Resources pro 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 můžete zavést i jen pro určité ovládací prvky daného typu, a to přiřazením klíče ke stylu a zadáním daného klíče ve vlastnosti Style ovládacího prvku. Další informace o stylech najdete v části o stylech a šablonách.

Vytvoření šablony ControlTemplate

Style umožňuje nastavit vlastnosti několika ovládacích prvků najednou, ale někdy může být žádoucí přizpůsobit vzhled Control nad rámec toho, co je možné vytvořením Style. Třídy, které dědí z třídy Control, mají vlastnost ControlTemplate, která definuje strukturu a vzhled pro Control. Vlastnost Template objektu Control je veřejná, můžete tedy zadat Control a ControlTemplate, které se liší od výchozí hodnoty. Často můžete zadat nové ControlTemplate pro Control místo dědění z ovládacího prvku a přizpůsobit si tak vzhled prvku Control.

Považme velmi běžný ovládací prvek Button. Hlavním chováním prvku Button je umožnit aplikaci provést nějakou akci, když uživatel na prvek klikne. Standardně se Button ve WPF zobrazuje jako vyvýšený obdélník. Při vývoji aplikace můžete chtít využít chování prvku Button, tedy zpracovat událost kliknutí na tlačítko, ale zároveň změnit vzhled tlačítka mnohem více, než je možné změnami jeho vlastností. V tomto případě můžete vytvořit nové ControlTemplate.

Následující příklad vytvoří ControlTemplate pro Button. ControlTemplate vytvoří Button se zaoblenými rohy a přechodem na pozadí. ControlTemplate obsahuje Border, jehož Background je LinearGradientBrush se dvěma objekty GradientStop. První GradientStop používá datovou vazbu, pomocí níž sváže vlastnost Color objektu GradientStop s barvou pozadí tlačítka. Když nastavíte vlastnost Background objektu Button, barva dané hodnoty se použije jako první GradientStop. Další informace o datových vazbách najdete v přehledu datových vazeb. Příklad vytváří i Trigger, které mění vzhled Button, když IsPressed je 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>

Poznámka:

Aby příklad fungoval, jak má, musí se vlastnost Background objektu Button nastavit na SolidColorBrush.

Přihlášení k odběru událostí

Přihlásit se k odběru události ovládacího prvku můžete pomocí jazyka XAML nebo kódu, ale zpracovat událost je možné pouze v kódu. Následující příklad ukazuje, jak se přihlásit k odběru události Click objektu 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

Následující příklad zpracovává událost Click objektu 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

Formátovaný obsah v ovládacích prvcích

Většina tříd, které dědí z třídy Control, můžou mít formátovaný obsah. Například Label může obsahovat libovolný objekt, třeba řetězec, Image nebo Panel. Následující třídy nabízejí podporu formátovaného obsahu a chovají se jako základní třídy většiny ovládacích prvků ve WPF.

Další informace o těchto základních třídách najdete v části o modelu obsahu WPF.

Viz také