Co jsou ovládací prvky?

Windows Presentation Foundation (WPF) obsahuje mnoho běžných součástí uživatelského rozhraní, které používáte v téměř každé aplikaci pro Windows, jako Button, Label, TextBox, Menu a ListBox. Historicky vývojáři tyto objekty nazývali ovládacími prvky. Vývojáři používají výraz "control" volně k označení jakékoli třídy, která představuje viditelný objekt v aplikaci. Třída nemusí dědit z třídy Control, aby měla viditelnou přítomnost. Třídy, které dědí z třídy Control obsahují ControlTemplate, což umožňuje příjemci ovládacího prvku radikálně změnit vzhled ovládacího prvku, aniž by bylo nutné vytvořit novou podtřídu. Tento článek popisuje, jak používat ovládací prvky (jak ty, které dědí z Control třídy, tak ty, které nejsou) 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. Představte si například následující obrázek okna WPF, které uživatele požádá o jméno a adresu:

Snímek obrazovky aplikace WPF se dvěma textovými poli označenými názvem a adresou Jsou viditelná dvě tlačítka. Jedno tlačítko má název Obnovit a druhé Odeslat.

Toto okno má šest ovládacích prvků: dva popisky, dvě textová pole a dvě tlačítka. Aplikace k vytvoření těchto ovládacích prvků používá XAML, jak je znázorněno v následujícím fragmentu kódu:

<Window x:Class="Examples.ExampleApp"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Input Record" Height="Auto" Width="300" SizeToContent="Height">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label>Enter your name:</Label>
        <TextBox Grid.Row="0" Grid.Column="1" Name="FirstName" Margin="2" />

        <Label Grid.Row="1">Enter your address:</Label>
        <TextBox Grid.Row="1" Grid.Column="1" Name="LastName" Margin="2" />

        <Button Grid.Row="2" Grid.Column="0" Name="Reset" Margin="2">Reset</Button>
        <Button Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2">Submit</Button>
    </Grid>
</Window>

Všechny ovládací prvky můžete vytvořit podobně v XAML. Stejné okno můžete vytvořit také v kódu:

// Grid container which is the content of the Window
Grid container = new() { Margin = new Thickness(5) };
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());

// Create the two labels, assign the second label to the second row
Label labelName = new() { Content = "Enter your name:" };
container.Children.Add(labelName);

Label labelAddress = new() { Content = "Enter your address:" };
Grid.SetRow(labelAddress, 1);
container.Children.Add(labelAddress);

// Create the two textboxes, assign both to the second column and
// assign the second textbox to the second row.
TextBox textboxName = new() { Margin = new Thickness(2) };
Grid.SetColumn(textboxName, 1);
container.Children.Add(textboxName);

TextBox textboxAddress = new() { Margin = new Thickness(2) };
Grid.SetRow(textboxAddress, 1);
Grid.SetColumn(textboxAddress, 1);
container.Children.Add(textboxAddress);

// Create the two buttons, assign both to the third row and
// assign the second button to the second column.
Button buttonReset = new() { Margin = new Thickness(2), Content = "Reset" };
Grid.SetRow(buttonReset, 2);
container.Children.Add(buttonReset);

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };
Grid.SetColumn(buttonSubmit, 1);
Grid.SetRow(buttonSubmit, 2);
container.Children.Add(buttonSubmit);

// Create the popup window and assign the container (Grid) as its content
Window inputWindow = new()
{
    Title = "Input Record",
    Height = double.NaN,
    Width = 300,
    SizeToContent = SizeToContent.Height,
    Content = container
};

inputWindow.Show();
' Grid container which is the content of the Window
Dim container As New Grid() With {.Margin = New Thickness(5)}
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())

' Create the two labels, assign the second label to the second row
Dim labelName As New Label() With {.Content = "Enter your name:"}
container.Children.Add(labelName)

Dim labelAddress As New Label() With {.Content = "Enter your address:"}
Grid.SetRow(labelAddress, 1)
container.Children.Add(labelAddress)

' Create the two textboxes, assign both to the second column and
' assign the second textbox to the second row.
Dim textboxName As New TextBox() With {.Margin = New Thickness(2)}
Grid.SetColumn(textboxName, 1)
container.Children.Add(textboxName)

Dim textboxAddress As New TextBox() With {.Margin = New Thickness(2)}
Grid.SetRow(textboxAddress, 1)
Grid.SetColumn(textboxAddress, 1)
container.Children.Add(textboxAddress)

' Create the two buttons, assign both to the third row and
' assign the second button to the second column.
Dim buttonReset As New Button() With {.Margin = New Thickness(2), .Content = "Reset"}
Grid.SetRow(buttonReset, 2)
container.Children.Add(buttonReset)

Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}
Grid.SetColumn(buttonSubmit, 1)
Grid.SetRow(buttonSubmit, 2)
container.Children.Add(buttonSubmit)

' Create the window and assign the container (Grid) as its content
Dim inputWindow As New Window() With
{
    .Title = "Input Record",
    .Height = Double.NaN,
    .Width = 300,
    .SizeToContent = SizeToContent.Height,
    .Content = container
}

inputWindow.Show()

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

Událost ovládacího prvku můžete přihlásit k odběru pomocí XAML nebo kódu, ale můžete zpracovat pouze událost v kódu.

V JAZYCE XAML nastavte událost jako atribut prvku. Zápis <Element.Event>handler<Element.Event> nelze použít pro události. Následující ukázka kódu ukazuje, jak se přihlásit k odběru události ClickButton:

<Button Click="Submit_Click" Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2">Submit</Button>

Tady je postup, jak to samé udělat v kódu:

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };
buttonSubmit.Click += Submit_Click;
Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}
AddHandler buttonSubmit.Click, AddressOf Submit_Click

Následující fragment kódu zpracovává Click událost Button:

private void Submit_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Someone clicked the submit button.");
}
Private Sub Submit_Click(sender As Object, e As Windows.RoutedEventArgs)
    MessageBox.Show("Someone clicked the submit button.")
End Sub

Změna vzhledu ovládacího prvku

Vzhled ovládacího prvku se běžně mění tak, aby odpovídal vzhledu a chování aplikace. Vzhled ovládacího prvku můžete změnit provedením některého z následujících postupů v závislosti na tom, co chcete udělat:

  • Změňte hodnotu vlastnosti ovládacího prvku.
  • Vytvořte Style pro ovládací prvek.
  • Vytvořte pro ovládací prvek nový ControlTemplate.

Změna vlastnosti ovládacího prvku

Mnoho ovládacích prvků má vlastnosti, které můžete použít ke změně způsobu zobrazení ovládacího prvku, například pozadí tlačítka. Nastavte vlastnosti hodnoty v XAML a v kódu. Následující příklad nastaví Background, FontSize a FontWeight vlastnosti na Button v XAML:

<Button Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2" Content="Submit">
    <Button.FontSize>18</Button.FontSize>
    <Button.FontWeight>Bold</Button.FontWeight>
    <Button.Background>
        <LinearGradientBrush>
            <GradientStop Color="#0073E6" Offset="0.0" />
            <GradientStop Color="#81D4FA" Offset="0.9" />
        </LinearGradientBrush>
    </Button.Background>
</Button>

Tady je postup, jak to samé udělat v kódu:

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };
buttonSubmit.FontSize = 18f;
buttonSubmit.FontWeight = FontWeights.Bold;
buttonSubmit.Background =
    new LinearGradientBrush(
        (Color)ColorConverter.ConvertFromString("#0073E6"),
        (Color)ColorConverter.ConvertFromString("#81D4FA"),
        new Point(0d, 0d),
        new Point(0.9d, 0d));
Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}
buttonSubmit.FontSize = 18.0F
buttonSubmit.FontWeight = FontWeights.Bold
buttonSubmit.Background =
        New LinearGradientBrush(
            ColorConverter.ConvertFromString("#0073E6"),
            ColorConverter.ConvertFromString("#81D4FA"),
            New Point(0D, 0D),
            New Point(0.9D, 0D))

Následující obrázek znázorňuje ukázkové okno:

Snímek obrazovky aplikace WPF se dvěma textovými poli označenými názvem a adresou Jsou viditelná dvě tlačítka. Jedno tlačítko má název Obnovit a druhé odeslat. Tlačítko Odeslat má přechodové pozadí, které přechází z modré na světlejší modrou.

Vytvoření stylu ovládacího prvku

WPF poskytuje rozsáhlou možnost určit vzhled ovládacích prvků vytvořením Style, místo nastavení vlastností u každého ovládacího prvku. Definice Style obvykle určujete v jazyce XAML v rámci ResourceDictionary, například ve vlastnosti Resources ovládacího prvku nebo okna. Prostředky se vztahují na obor, ve kterém je deklarujete. Další informace najdete v tématu Přehled prostředků XAML.

Následující příklad použije Style na každý Button obsažený ve stejném Grid, který definuje styl:

<Grid.Resources>
    <Style TargetType="{x:Type Button}">
        <Style.Setters>
            <Setter Property="FontSize" Value="18" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Background">
                <Setter.Value>
                    <LinearGradientBrush>
                        <GradientStop Color="#0073E6" Offset="0.0" />
                        <GradientStop Color="#81D4FA" Offset="0.9" />
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style.Setters>
    </Style>
</Grid.Resources>

Tady je postup, jak to samé udělat v kódu:

Grid container = new() { Margin = new Thickness(5) };
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());

Style buttonStyle = new(typeof(Button));
buttonStyle.Setters.Add(new Setter(Button.FontSizeProperty, 18d));
buttonStyle.Setters.Add(new Setter(Button.FontWeightProperty, FontWeights.Bold));
buttonStyle.Setters.Add(new Setter(Button.BackgroundProperty,
    new LinearGradientBrush(
        (Color)ColorConverter.ConvertFromString("#0073E6"),
        (Color)ColorConverter.ConvertFromString("#81D4FA"),
        new Point(0d, 0d),
        new Point(0.9d, 0d))));

container.Resources.Add(typeof(Button), buttonStyle);
Dim container As New Grid() With {.Margin = New Thickness(5)}
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())

Dim buttonStyle As New Style(GetType(Button))
buttonStyle.Setters.Add(New Setter(Button.FontSizeProperty, 18.0R))
buttonStyle.Setters.Add(New Setter(Button.FontWeightProperty, FontWeights.Bold))
buttonStyle.Setters.Add(New Setter(Button.BackgroundProperty,
        New LinearGradientBrush(
            ColorConverter.ConvertFromString("#0073E6"),
            ColorConverter.ConvertFromString("#81D4FA"),
            New Point(0D, 0D),
            New Point(0.9D, 0D))))

container.Resources.Add(GetType(Button), buttonStyle)

Následující obrázek znázorňuje styl použitý v mřížce okna, který změní vzhled dvou tlačítek:

Snímek obrazovky aplikace WPF se dvěma textovými poli označenými názvem a adresou Jsou viditelná dvě tlačítka. Jedno tlačítko má název Obnovit a druhé Odeslat. Obě tlačítka obsahují přechodové pozadí, které přechází z modré na světlejší modrou.

Místo použití stylu u všech ovládacích prvků určitého typu ho můžete přiřadit konkrétním ovládacím prvkům tak, že do stylu ve slovníku prostředků přidáte klíč a na tento klíč ve Style vlastnosti ovládacího prvku odkazujete. Další informace o stylech naleznete v tématu Stylování a Šablonování.

Vytvořte ControlTemplate

Nastaví Style vlastnosti na více ovládacích prvcích najednou, ale někdy potřebujete přizpůsobit vzhled ovládacího prvku nad rámec toho, co můžete dělat s Style. Třídy, které dědí z Control třídy mají ControlTemplate, který definuje strukturu a vzhled ovládacího prvku.

Zvažte Button ovládací prvek, běžně používaný ovládací prvek, který používá téměř každá aplikace. Primárním chováním tlačítka je umožnit aplikaci provést nějakou akci, když uživatel tlačítko vybere. Ve výchozím nastavení se tlačítko ve WPF zobrazí jako vyvýšený obdélník. Při vývoji aplikace můžete chtít využít chování tlačítka – to znamená způsob interakce uživatele s tlačítkem, který vyvolá Click událost – ale vzhled tlačítka můžete změnit nad rámec toho, co můžete udělat změnou vlastností tlačítka. V tomto případě můžete vytvořit novou ControlTemplate.

Následující příklad vytvoří ControlTemplate pro Button. ControlTemplate vytváří vizuál pro Button, který představuje ohraničení se zaoblenými rohy a přechodovým pozadím.

<Button Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2" Content="Submit">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border Name="Border" CornerRadius="10" 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="PeachPuff" 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="LightBlue" Offset="0.9" />
                            </LinearGradientBrush>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>

Poznámka:

Nastavte vlastnost Background u Button na SolidColorBrush pro správné fungování příkladu.

Tady je postup, jak to samé udělat v kódu. Následující kód vytvoří řetězec XAML a parsuje ho za účelem vygenerování šablony, kterou můžete použít. Tento přístup je podporovaný způsob generování šablony za běhu.

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };

// Create the XAML used to define the button template
const string xaml = """
    <ControlTemplate TargetType="Button">
        <Border Name="Border" CornerRadius="10" 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="PeachPuff" 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="LightBlue" Offset="0.9" />
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    """;

// Load the XAML into a stream that can be parsed
using MemoryStream stream = new(System.Text.Encoding.UTF8.GetBytes(xaml));

// Create a parser context and add the default namespace and 
// the x namespace, which is common to WPF XAML
System.Windows.Markup.ParserContext context = new();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

// Parse the XAML and assign it to the button's template
buttonSubmit.Template = (ControlTemplate)System.Windows.Markup.XamlReader.Load(stream, context);

// Set the other properties of the button
Grid.SetColumn(buttonSubmit, 1);
Grid.SetRow(buttonSubmit, 2);

// Assign the button to the grid container
container.Children.Add(buttonSubmit);
Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}

' Create the XAML used to define the button template
Const xaml As String = "
    <ControlTemplate TargetType=""Button"">
        <Border Name=""Border"" CornerRadius=""10"" 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=""PeachPuff"" 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=""LightBlue"" Offset=""0.9"" />
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>"

' Load the XAML into a stream that can be parsed
Using stream As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(xaml))

    ' Create a parser context and add the default namespace and 
    ' the x namespace, which is common to WPF XAML
    Dim context = New System.Windows.Markup.ParserContext()
    context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation")
    context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml")

    ' Parse the XAML and assign it to the button's template
    buttonSubmit.Template = System.Windows.Markup.XamlReader.Load(stream, context)
End Using

' Set the other properties of the button
Grid.SetColumn(buttonSubmit, 1)
Grid.SetRow(buttonSubmit, 2)

' Assign the button to the grid container
container.Children.Add(buttonSubmit)

Následující obrázek ukazuje, jak šablona vypadá při použití:

Snímek obrazovky aplikace WPF se dvěma textovými poli označenými názvem a adresou Jsou viditelná dvě tlačítka. Jedno tlačítko má název Obnovit a druhé odeslat. Tlačítko Odeslat má zaoblené rohy a barvu broskve.

V předchozím příkladu použijete ControlTemplate na jedno tlačítko. Můžete ale přiřadit ControlTemplate k Style a použít ho u všech tlačítek, jak je ukázáno v části Vytvoření stylu pro ovládací prvek.

Další informace o tom, jak využít jedinečné funkce, které šablona poskytuje, najdete v tématu Styling a Šablonování.

Bohatý obsah v ovládacích prvcích

Většina tříd, které dědí z Control třídy, může obsahovat bohatý obsah. Například Label může obsahovat libovolný objekt, například řetězec, Imagenebo Panel. Následující třídy poskytují podporu pro bohatý obsah a fungují jako základní třídy pro většinu ovládacích prvků ve WPF: