Controls
Windows Presentation Foundation (WPF) ships with many of the common UI components that are used in almost every Windows application, such as Button, Label, TextBox, Menu, and ListBox. Historically, these objects have been referred to as controls. While the WPF SDK continues to use the term "control" to loosely mean any class that represents a visible object in an application, it is important to note that a class does not need to inherit from the Control class to have a visible presence. Classes that inherit from the Control class contain a ControlTemplate, which allows the consumer of a control to radically change the control's appearance without having to create a new subclass. This topic discusses how controls (both those that do inherit from the Control class and those that do not) are commonly used in WPF.
This topic contains the following sections.
- Creating an Instance of a Control
- Changing the Appearance of a Control
- Subscribing to Events
- Rich Content in Controls
- Related Topics
Creating an Instance of a Control
You can add a control to an application by using either Extensible Application Markup Language (XAML) or code. The following example shows how to create a simple application that asks a user for their first and last name. This example creates six controls: two labels, two text boxes, and two buttons, in XAML. All controls can be created similarly.
<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>
The following example creates the same application in code. For brevity, the creation of the Grid, grid1, has been excluded from the sample. grid1 has the same column and row definitions as shown in the preceding XAML example.
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 'CreateControls
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);
}
Changing the Appearance of a Control
It is common to change the appearance of a control to fit the look and feel of your application. You can change the appearance of a control by doing one of the following, depending on what you want to accomplish:
Change the value of a property of the control.
Create a Style for the control.
Create a new ControlTemplate for the control.
Changing a Control's Property Value
Many controls have properties that allow you to change how the control appears, such as the Background of a Button. You can set the value properties in both XAML and code. The following example sets the Background, FontSize, and FontWeight properties on a Button in 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>
The following example sets the same properties in code.
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
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;
Creating a Style for a Control
WPF gives you the ability to specify the appearance of controls wholesale, instead of setting properties on each instance in the application, by creating a Style. The following example creates a Style that is applied to each Button in the application. Style definitions are typically defined in XAML in a ResourceDictionary, such as the Resources property of the 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>
You can also apply a style to only certain controls of a specific type by assigning a key to the style and specifying that key in the Style property of your control. For more information about styles, see Styling and Templating.
Creating a ControlTemplate
A Style allows you to set properties on multiple controls at a time, but sometimes you might want to customize the appearance of a Control beyond what you can do by creating a Style. Classes that inherit from the Control class have a ControlTemplate, which defines the structure and appearance of a Control. The Template property of a Control is public, so you can give a Control a ControlTemplate that is different than its default. You can often specify a new ControlTemplate for a Control instead of inheriting from a control to customize the appearance of a Control.
Consider the very common control, Button. The primary behavior of a Button is to enable an application to take some action when the user clicks it. By default, the Button in WPF appears as a raised rectangle. While developing an application, you might want to take advantage of the behavior of a Button--that is, by handling the button's click event--but you might change the button's appearance beyond what you can do by changing the button's properties. In this case, you can create a new ControlTemplate.
The following example creates a ControlTemplate for a Button. The ControlTemplate creates a Button with rounded corners and a gradient background. The ControlTemplate contains a Border whose Background is a LinearGradientBrush with two GradientStop objects. The first GradientStop uses data binding to bind the Color property of the GradientStop to the color of the button's background. When you set the Background property of the Button, the color of that value will be used as the first GradientStop. For more information about data binding, see Data Binding Overview. The example also creates a Trigger that changes the appearance of the Button when IsPressed is 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>
Note |
---|
The Background property of the Button must be set to a SolidColorBrush for the example to work properly. |
Subscribing to Events
You can subscribe to a control's event by using either XAML or code, but you can only handle an event in code. The following example shows how to subscribe to the Click event of a Button.
<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName" Click="submit_Click"
Background="Green">View message</Button>
AddHandler submit.Click, AddressOf submit_Click
submit.Click += new RoutedEventHandler(submit_Click);
The following example handles the Click event of a Button.
Private Sub submit_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text)
End Sub 'submit_Click
void submit_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
}
Rich Content in Controls
Most classes that inherit from the Control class have the capacity to contain rich content. For example, a Label can contain any object, such as a string, an Image, or a Panel. The following classes provide support for rich content and act as base classes for most of the controls in WPF.
ContentControl-- Some examples of classes that inherit from this class are Label, Button, and ToolTip.
ItemsControl-- Some examples of classes that inherit from this class are ListBox, Menu, and StatusBar.
HeaderedContentControl-- Some examples of classes that inherit from this class are TabItem, GroupBox, and Expander.
HeaderedItemsControl--Some examples of classes that inherit from this class are MenuItem, TreeViewItem, and ToolBar.
For more information about these base classes, see WPF Content Model.