Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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, Menui ListBox. W przeszłości te obiekty są określane jako kontrolki. Termin "kontrola" jest używany luźno, aby oznaczać dowolną klasę reprezentującą widoczny obiekt w aplikacji. Należy pamiętać, że klasa nie musi dziedziczyć z klasy Control aby mieć widoczną obecność. Klasy dziedziczone z klasy Control
zawierają ControlTemplate, co umożliwia użytkownikowi kontrolki radykalną zmianę wyglądu kontrolki bez konieczności tworzenia nowej podklasy. W tym artykule omówiono sposób, w jaki kontrolki (zarówno te, które dziedziczą z Control
klasy, jak i te, które nie są) są często używane w WPF.
Utwórz wystąpienie kontrolki
Kontrolkę można dodać do aplikacji przy użyciu języka XAML (Extensible Application Markup Language) lub kodu. Rozważmy na przykład poniższą ilustrację okna WPF, które prosi użytkownika o podanie ich nazwy i adresu:
To okno ma sześć kontrolek: dwie etykiety, dwa pola tekstowe i dwa przyciski. Język XAML służy do tworzenia tych kontrolek, jak pokazano w poniższym fragmencie kodu:
<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>
Wszystkie kontrolki można utworzyć podobnie w języku XAML. To samo okno można utworzyć w kodzie:
// 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()
Zapisz się na wydarzenia
Możesz subskrybować zdarzenie kontrolki za pomocą języka XAML lub kodu, ale możesz obsługiwać zdarzenie tylko w kodzie.
W języku XAML zdarzenie jest ustawiane jako atrybut elementu. Nie można używać <Element.Event>handler<Element.Event>
notacji dla zdarzeń. Poniższy fragment kodu pokazuje, jak podłączyć się do Click
zdarzenia Button:
<Button Click="Submit_Click" Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2">Submit</Button>
Oto jak wykonać to samo w kodzie:
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
Poniższy fragment obsługuje zdarzenie Click
dla 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
Zmienianie wyglądu kontrolki
Często zmienia się wygląd kontrolki, aby dopasować wygląd i działanie aplikacji. Wygląd kontrolki można zmienić, wykonując jedną z następujących czynności, w zależności od tego, co chcesz osiągnąć:
- Zmień wartość właściwości kontrolki.
- Utwórz Style dla kontrolki.
- Utwórz nowy ControlTemplate dla kontrolki.
Zmienianie właściwości kontrolki
Wiele kontrolek ma właściwości, które umożliwiają zmianę sposobu wyświetlania kontrolki, na przykład tła przycisku. Właściwości wartości można ustawić zarówno w języku XAML, jak i kodzie. Poniższy przykład ustawia Background, FontSize i FontWeight na obiekcie Button
w 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>
Oto jak wykonać to samo w kodzie:
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))
Przykładowe okno wygląda teraz jak na poniższej ilustracji:
Tworzenie stylu dla kontrolki
WPF umożliwia rozbudowane określanie wyglądu kontrolek przez utworzenie Styleobiektu , zamiast ustawiania właściwości dla każdej kontrolki.
Style
definicje są zwykle definiowane w języku XAML w ResourceDictionarykodzie , na przykład Resources właściwość kontrolki lub okna. Zasoby są stosowane do zakresu, w którym są deklarowane. Aby uzyskać więcej informacji, zobacz Omówienie zasobów XAML.
Poniższy przykład stosuje Style
do każdego Button zawartego w tym samym Grid
, który określa 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>
Oto jak wykonać to samo w kodzie:
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)
Na poniższej ilustracji przedstawiono styl zastosowany do siatki okna, który zmienia wygląd dwóch przycisków:
Zamiast stosować styl do wszystkich kontrolek określonego typu, można je również przypisać do określonych kontrolek, dodając klucz do stylu w słowniku zasobów i odwołując się do tego klucza we Style
właściwości kontrolki. Aby uzyskać więcej informacji na temat stylów, zobacz Stylizacja i Szablonowanie.
Utwórz ControlTemplate
Element Style
umożliwia ustawienie właściwości na wielu kontrolkach jednocześnie, ale czasami możesz chcieć dostosować wygląd kontrolki poza tym, co można zrobić za pomocą elementu Style. Klasy dziedziczące z Control mają element ControlTemplate, który definiuje strukturę i wygląd kontrolki.
Weź pod uwagę kontrolkę Button , wspólną kontrolkę używaną przez prawie każdą aplikację. Podstawowym zachowaniem przycisku jest umożliwienie aplikacji podjęcia pewnych działań po wybraniu przycisku przez użytkownika. Domyślnie przycisk w WPF jest wyświetlany jako podniesiony prostokąt. Podczas tworzenia aplikacji możesz chcieć skorzystać z zachowania przycisku — czyli sposobu interakcji użytkownika z przyciskiem, który wywołuje Click
zdarzenie — ale możesz zmienić wygląd przycisku poza tym, co można zrobić, zmieniając właściwości przycisku. W takim przypadku można utworzyć nowy ControlTemplate.
Poniższy przykład tworzy obiekt ControlTemplate dla Button. Obiekt ControlTemplate
tworzy wizualizację dla Button
z obramowaniem o zaokrąglonych rogach i gradientowym tłem.
<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>
Uwaga / Notatka
Aby przykład działał prawidłowo, właściwość Background elementu Button musi być ustawiona na SolidColorBrush.
Oto jak zrobić to samo w kodzie. Poniższy kod tworzy ciąg XAML i analizuje go w celu wygenerowania szablonu, który można zastosować, co jest obsługiwanym sposobem generowania szablonu w czasie wykonywania.
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)
Na poniższej ilustracji przedstawiono wygląd szablonu po zastosowaniu:
W poprzednim przykładzie element ControlTemplate
jest stosowany do pojedynczego przycisku. Można jednak przypisać element ControlTemplate
i zastosowany do Style
wszystkich przycisków, podobnie jak pokazano w sekcji Tworzenie stylu dla kontrolki .
Aby uzyskać więcej informacji na temat korzystania z unikatowych funkcji oferowanych przez szablon, zobacz Stylowanie i Szablonowanie.
Bogata zawartość w elementach sterujących
Większość klas dziedziczących z klasy Control może zawierać bogatą zawartość. Na przykład Label może zawierać dowolny obiekt, taki jak ciąg, Imagelub Panel. Następujące klasy zapewniają obsługę rozbudowanej zawartości i działają jako klasy bazowe dla większości kontrolek w WPF:
ContentControl— Niektóre przykłady klas dziedziczone z tej klasy to Label, Buttoni ToolTip.
ItemsControl— Niektóre przykłady klas dziedziczone z tej klasy to ListBox, Menui StatusBar.
HeaderedContentControl— Niektóre przykłady klas dziedziczone z tej klasy to TabItem, GroupBoxi Expander.
HeaderedItemsControl— Niektóre przykłady klas dziedziczone z tej klasy to MenuItem, TreeViewItemi ToolBar.
Treści powiązane
.NET Desktop feedback