Bagikan melalui


Apa itu kontrol?

Windows Presentation Foundation (WPF) dikirim dengan banyak komponen UI umum yang digunakan di hampir setiap aplikasi Windows, seperti Button, , LabelTextBox, Menu, dan ListBox. Secara historis, objek-objek ini disebut sebagai kontrol. Istilah "kontrol" digunakan secara longgar untuk berarti kelas apa pun yang mewakili objek yang terlihat dalam aplikasi. Penting untuk dicatat bahwa sebuah kelas tidak perlu mewarisi dari kelas Control untuk memiliki keberadaan yang dapat dilihat. Kelas yang mewarisi dari kelas Control berisi ControlTemplate, yang memungkinkan konsumen kontrol untuk secara radikal mengubah tampilan kontrol tanpa harus membuat subkelas baru. Artikel ini membahas bagaimana kontrol (baik yang mewarisi dari kelas Control maupun yang tidak) umumnya digunakan dalam WPF.

Membuat instance dari sebuah kontrol

Anda dapat menambahkan kontrol ke aplikasi dengan menggunakan Extensible Application Markup Language (XAML) atau kode. Misalnya, pertimbangkan gambar jendela WPF berikut yang meminta nama dan alamat pengguna:

Cuplikan layar aplikasi WPF dengan dua kotak teks berlabel nama dan alamat. Dua tombol terlihat. Satu tombol diberi nama 'Reset' dan tombol lainnya 'Kirim.'

Jendela ini memiliki enam kontrol: dua label, dua kotak teks, dan dua tombol. XAML digunakan untuk membuat kontrol ini, seperti yang ditunjukkan dalam cuplikan berikut:

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

Semua kontrol dapat dibuat serupa di XAML. Jendela yang sama dapat dibuat dalam kode:

// 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()

Berlangganan Peristiwa

Anda dapat berlangganan peristiwa kontrol dengan menggunakan XAML atau kode, tetapi Anda hanya dapat menangani peristiwa dalam kode.

Di XAML, peristiwa diatur sebagai atribut pada elemen . Anda tidak dapat menggunakan notasi <Element.Event>handler<Element.Event> untuk event. Cuplikan berikut menunjukkan cara berlangganan acara Click dari Button:

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

Dan berikut cara melakukan hal yang sama dalam kode:

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

Cuplikan berikut menangani acara Click dari 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

Mengubah tampilan kontrol

Adalah umum untuk mengubah tampilan kontrol agar sesuai dengan tampilan dan nuansa aplikasi Anda. Anda dapat mengubah tampilan kontrol dengan melakukan salah satu hal berikut, tergantung pada apa yang ingin Anda capai:

  • Ubah nilai properti kontrol.
  • Buat Style untuk kontrol.
  • Buat ControlTemplate baru untuk pengendalian.

Mengubah kontrol properti

Banyak kontrol memiliki properti yang memungkinkan Anda mengubah tampilan kontrol, seperti latar belakang tombol. Anda dapat mengatur properti nilai di XAML dan kode. Contoh berikut mengatur Background, FontSize, dan FontWeight properti pada Button di 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>

Dan berikut cara melakukan hal yang sama dalam kode:

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

Jendela contoh sekarang terlihat seperti gambar berikut:

Cuplikan layar aplikasi WPF dengan dua kotak teks berlabel nama dan alamat. Dua tombol terlihat. Satu tombol diberi nama 'Reset' dan tombol lainnya 'Kirim.' Tombol 'Kirim' memiliki latar belakang gradien yang beralih dari biru ke biru yang lebih muda.

Buat gaya untuk kontrol

WPF memberi Anda kemampuan yang luas untuk menentukan tampilan kontrol dengan membuat Style, alih-alih mengatur properti pada setiap kontrol. Style definisi biasanya didefinisikan dalam XAML dalam ResourceDictionary, seperti Resources properti kontrol atau Jendela. Sumber daya diterapkan pada cakupan di mana mereka dideklarasikan. Untuk informasi selengkapnya, lihat Gambaran Umum sumber daya XAML.

Contoh berikut menerapkan Style ke setiap Button yang terkandung dalam elemen Grid yang sama yang menentukan gaya.

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

Dan berikut cara melakukan hal yang sama dalam kode:

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)

Gambar berikut menunjukkan gaya yang diterapkan ke kisi jendela, yang mengubah tampilan dua tombol:

Cuplikan layar aplikasi WPF dengan dua kotak teks berlabel nama dan alamat. Dua tombol terlihat. Satu tombol diberi nama 'Reset' dan tombol lainnya 'Kirim.' Kedua tombol memiliki latar belakang gradien yang beralih dari biru ke biru yang lebih muda.

Daripada menerapkan gaya ke semua kontrol dari jenis tertentu, gaya dapat ditetapkan secara spesifik ke kontrol tertentu dengan menambahkan sebuah kunci ke gaya tersebut dalam kamus sumber daya, serta mereferensikan kunci itu dalam properti Style dari kontrol tersebut. Untuk informasi selengkapnya tentang tata letak, lihat Penggayaan dan Pembuatan Template.

Membuat ControlTemplate

A Style memungkinkan Anda untuk mengatur properti pada beberapa kontrol pada satu waktu, tetapi kadang-kadang Anda mungkin ingin menyesuaikan tampilan kontrol di luar apa yang dapat Anda lakukan dengan Style. Kelas yang mewarisi dari Control kelas memiliki ControlTemplate, yang menentukan struktur dan tampilan kontrol.

Pertimbangkan kontrol Button, yaitu kontrol umum yang digunakan oleh hampir setiap aplikasi. Perilaku utama tombol adalah mengaktifkan aplikasi untuk mengambil beberapa tindakan saat pengguna memilih tombol . Secara default, tombol di WPF muncul sebagai persegi panjang yang dinaikkan. Saat mengembangkan aplikasi, Anda mungkin ingin memanfaatkan perilaku tombol—yaitu, bagaimana pengguna berinteraksi dengan tombol, yang memicu peristiwa Click—tetapi Anda mungkin mengubah tampilan tombol lebih dari sekadar mengubah properti tombol. Dalam hal ini, Anda dapat membuat ControlTemplatebaru.

Contoh berikut membuat ControlTemplate untuk Button. ControlTemplate membuat visual untuk Button yang menyajikan batas dengan sudut bulat dan latar belakang gradien.

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

Nota

Properti Background dari Button harus diatur ke SolidColorBrush agar contoh dapat berfungsi dengan benar.

Dan inilah cara melakukan hal yang sama dalam kode. Kode berikut membuat string XAML dan menguraikannya untuk menghasilkan templat yang dapat diterapkan, yang merupakan cara yang didukung untuk menghasilkan templat pada run-time.

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)

Gambar berikut menunjukkan seperti apa templat saat diterapkan:

Cuplikan layar aplikasi WPF dengan dua kotak teks berlabel nama dan alamat. Dua tombol terlihat. Satu tombol diberi nama 'Reset' dan tombol lainnya 'Kirim.' Tombol 'Kirim' memiliki sudut bulat dan warna persik yang diterapkan padanya.

Dalam contoh sebelumnya, ControlTemplate diterapkan ke satu tombol. Namun, ControlTemplate dapat ditetapkan ke Style dan diterapkan ke semua tombol, seperti apa yang ditunjukkan di bagian Buat gaya untuk kontrol .

Untuk informasi selengkapnya tentang cara memanfaatkan fitur unik yang disediakan templat, lihat Gaya dan Templat.

Konten yang kaya pada kontrol

Sebagian besar kelas yang mewarisi dari kelas Control memiliki kemampuan untuk mengandung konten yang kaya isi. Misalnya, Label dapat berisi objek apa pun, seperti string, Image, atau Panel. Kelas berikut memberikan dukungan untuk konten kaya dan bertindak sebagai kelas dasar untuk sebagian besar kontrol di WPF: