Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Windows Presentation Foundation (WPF) поставляется со многими общими компонентами пользовательского интерфейса, которые используются почти в каждом приложении Windows, например Button, Label, TextBoxMenuи ListBox. Исторически эти объекты называются элементами управления. Термин "control" используется в широком смысле для обозначения класса, представляющего видимый объект в приложении. Важно отметить, что классу не нужно наследовать от Control класса, чтобы иметь видимое присутствие. Классы, наследуемые от класса Control, содержат ControlTemplate, что позволяет потребителю элемента управления радикально изменить внешний вид элемента управления, не создавая новый подкласс. В этой статье описывается, как элементы управления (как те, которые наследуются от Control класса, так и те, которые не используются) обычно используются в WPF.
Создание экземпляра элемента управления
Вы можете добавить элемент управления в приложение с помощью языка разметки расширяемых приложений (XAML) или кода. Например, рассмотрим следующее изображение окна WPF, которое запрашивает у пользователя имя и адрес:
В этом окне есть шесть элементов управления: две метки, два текстовых поля и две кнопки. XAML используется для создания этих элементов управления, как показано в следующем фрагменте кода:
<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>
Все элементы управления можно создавать аналогичным образом в XAML. Это же окно можно создать в коде:
// 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()
Оформление подписки на события
Вы можете подписаться на событие элемента управления с помощью XAML или кода, но можно обрабатывать только событие в коде.
В XAML событие устанавливается в качестве атрибута элемента. Вы не можете использовать <Element.Event>handler<Element.Event> нотацию для событий. В следующем фрагменте показано, как подписаться на событие Click из Button.
<Button Click="Submit_Click" Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2">Submit</Button>
Вот как это сделать в коде:
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
Следующий фрагмент кода обрабатывает событие Click для 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
Изменение внешнего вида элемента управления
Обычно можно изменить внешний вид элемента управления, чтобы он соответствовал внешнему виду и чувству вашего приложения. Вы можете изменить внешний вид элемента управления, выполнив одно из следующих действий в зависимости от того, что вы хотите выполнить:
- Измените значение свойства элемента управления.
- Создайте Style для элемента управления.
- Создайте новую ControlTemplate для элемента управления.
Изменение свойства элемента управления
Многие элементы управления имеют свойства, позволяющие изменить способ отображения элемента управления, например фон кнопки. Свойства значения можно задать как в XAML, так и в коде. В следующем примере задаются свойства Background, FontSize и FontWeight в Button в 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>
Вот как это сделать в коде:
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))
Теперь окно примера выглядит следующим образом:
Создание стиля для элемента управления
WPF предоставляет широкие возможности задавать внешний вид элементов управления, создавая Style, вместо настройки свойств для каждого элемента управления.
Style Определения обычно определяются в XAML в ResourceDictionary, например, Resources свойство элемента управления или окна. Ресурсы применяются к области, в которой они объявлены. Дополнительные сведения см. в разделе "Обзор ресурсов XAML".
В следующем примере к каждому Style, содержащемуся в том же Button, который задает стиль, применяется Grid.
<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>
Вот как это сделать в коде:
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)
На следующем рисунке показан стиль, примененный к сетке окна, который изменяет внешний вид двух кнопок:
Вместо применения стиля ко всем элементам управления определенного типа они также могут быть назначены определенным элементам управления, добавив ключ в стиль в словаре ресурсов и ссылаясь на этот ключ в Style свойстве элемента управления. Для получения дополнительной информации о стилях см. Стилизация и шаблоны.
Создайте ControlTemplate
A Style позволяет задавать свойства для нескольких элементов управления одновременно, но иногда может потребоваться настроить внешний вид элемента управления по сравнению с тем, что можно сделать с помощью Style. Классы, наследуемые от Control класса, имеют значение ControlTemplate, определяющее структуру и внешний вид элемента управления.
Рассмотрим элемент Button управления, распространенный элемент управления, используемый почти каждым приложением. Основное поведение кнопки — разрешить приложению выполнять некоторые действия, когда пользователь выбирает кнопку. По умолчанию кнопка в WPF отображается как поднятый прямоугольник. При разработке приложения может потребоваться воспользоваться поведением кнопки, т. е. как пользователь взаимодействует с кнопкой, которая вызывает Click событие, но вы можете изменить внешний вид кнопки за рамки того, что можно сделать, изменив свойства кнопки. В этом случае можно создать новый ControlTemplate.
В следующем примере создается ControlTemplate для Button.
ControlTemplate создает визуальный элемент для Button, который представляет собой границу с закругленными углами и градиентным фоном.
<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>
Замечание
Свойство Background элемента Button должно быть установлено на SolidColorBrush для правильной работы примера.
И вот как это сделать в коде. Следующий код создает строку XAML и анализирует ее для создания шаблона, который можно применить, что является поддерживаемым способом создания шаблона во время выполнения.
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)
На следующем рисунке показано, как выглядит шаблон при применении:
В предыдущем примере ControlTemplate применяется к одной кнопке. Однако ControlTemplate можно назначить Style и применить ко всем кнопкам, как это показано в разделе «Создание стиля для элемента управления».
Дополнительные сведения о том, как воспользоваться уникальными функциями, предоставляемыми шаблоном, см. в разделе "Стилизация" и "Шаблон".
Насыщенный контент в элементах управления
Большинство классов, наследующих от класса Control, имеют емкость для хранения богатого содержимого. Например, Label может содержать любой объект, например строку, Imageили Panel. Следующие классы обеспечивают поддержку расширенного содержимого и выступают в качестве базовых классов для большинства элементов управления в WPF:
ContentControl — Некоторые примеры классов, которые наследуются от этого класса: Label, Button и ToolTip.
ItemsControl — Некоторые примеры классов, которые наследуются от этого класса: ListBox, Menu и StatusBar.
HeaderedContentControl — Некоторые примеры классов, которые наследуются от этого класса: TabItem, GroupBox и Expander.
HeaderedItemsControl — Некоторые примеры классов, которые наследуются от этого класса: MenuItem, TreeViewItem и ToolBar.
Связанный контент
- Стилизация и шаблонирование
- Обзор привязки данных
.NET Desktop feedback