Samouczek: tworzenie nowej aplikacji WPF przy użyciu platformy .NET

Z tego krótkiego samouczka dowiesz się, jak utworzyć nową aplikację Windows Presentation Foundation (WPF) za pomocą programu Visual Studio. Po wygenerowaniu początkowej aplikacji dowiesz się, jak dodawać kontrolki i jak obsługiwać zdarzenia. Na koniec tego samouczka będziesz mieć prostą aplikację, która dodaje nazwy do pola listy.

Ważne

Dokumentacja przewodnika dla komputerów dla platform .NET 7 i .NET 6 jest w budowie.

Z tego samouczka dowiesz się, jak wykonywać następujące czynności:

  • Tworzenie nowej aplikacji WPF
  • Dodawanie kontrolek do formularza
  • Obsługa zdarzeń sterowania w celu zapewnienia funkcjonalności aplikacji
  • Uruchom aplikację

Oto wersja zapoznawcza aplikacji, którą utworzysz, wykonując czynności opisane w tym samouczku:

Finished sample app for WPF tutorial

Wymagania wstępne

Napiwek

Użyj programu Visual Studio 2022 w wersji 17.4 lub nowszej i zainstaluj zarówno poszczególne składniki platformy .NET 7, jak i .NET 6. Dodano obsługę platformy .NET 7 w programie Visual Studio 2022 w wersji 17.4.

Tworzenie aplikacji WPF

Pierwszym krokiem tworzenia nowej aplikacji jest otwarcie programu Visual Studio i wygenerowanie aplikacji na podstawie szablonu.

  1. Otwórz program Visual Studio.

  2. Wybierz pozycję Utwórz nowy projekt.

    Create a new WPF project in Visual Studio 2022 for .NET. 6

  3. W polu Wyszukaj szablony wpisz wpf, a następnie naciśnij klawisz Enter.

  4. Z listy rozwijanej języka kodu wybierz pozycję C# lub Visual Basic.

  5. Na liście szablonów wybierz pozycję Aplikacja WPF, a następnie wybierz pozycję Dalej.

    Ważne

    Nie wybieraj szablonu Aplikacja WPF (.NET Framework).

    Na poniższej ilustracji przedstawiono zarówno szablony projektów C#, jak i Visual Basic .NET. Jeśli zastosowano filtr języka kodu, zobaczysz odpowiedni szablon.

    Search for the WPF template in Visual Studio 2022 for .NET. 6

  6. W oknie Konfigurowanie nowego projektu wykonaj następujące czynności:

    1. W polu Nazwa projektu wprowadź nazwy.
    2. Zaznacz pole wyboru Umieść rozwiązanie i projekt w tym samym katalogu.
    3. Opcjonalnie wybierz inną lokalizację , aby zapisać kod.
    4. Kliknij przycisk Next (Dalej).

    Configure new WPF project in Visual Studio 2022 for .NET 6

  7. W oknie Dodatkowe informacje wybierz pozycję .NET 6.0 (obsługa długoterminowa) dla platformy docelowej. Zaznacz przycisk Utwórz.

    Select target framework for new WPF project in Visual Studio 2022 for .NET 6

  1. Otwórz program Visual Studio.

  2. Wybierz pozycję Utwórz nowy projekt.

    Create a new WPF project in Visual Studio 2022 for .NET 7.

  3. W polu Wyszukaj szablony wpisz wpf, a następnie naciśnij klawisz Enter.

  4. Z listy rozwijanej języka kodu wybierz pozycję C# lub Visual Basic.

  5. Na liście szablonów wybierz pozycję Aplikacja WPF, a następnie wybierz pozycję Dalej.

    Ważne

    Nie wybieraj szablonu Aplikacja WPF (.NET Framework).

    Na poniższej ilustracji przedstawiono zarówno szablony projektów C#, jak i Visual Basic .NET. Jeśli zastosowano filtr języka kodu, zobaczysz odpowiedni szablon.

    Search for the WPF template in Visual Studio 2022 for .NET. 7

  6. W oknie Konfigurowanie nowego projektu wykonaj następujące czynności:

    1. W polu Nazwa projektu wprowadź nazwy.
    2. Zaznacz pole wyboru Umieść rozwiązanie i projekt w tym samym katalogu.
    3. Opcjonalnie wybierz inną lokalizację , aby zapisać kod.
    4. Kliknij przycisk Next (Dalej).

    Configure new WPF project in Visual Studio 2022 for .NET 7

  7. W oknie Dodatkowe informacje wybierz pozycję .NET 7.0 (obsługa terminów standardowych) dla platformy docelowej. Zaznacz przycisk Utwórz.

    Select target framework for new WPF project in Visual Studio 2022 for .NET 7

Po wygenerowaniu aplikacji program Visual Studio powinien otworzyć okienko projektanta XAML dla okna domyślnego MainWindow. Jeśli projektant nie jest widoczny, kliknij dwukrotnie plik MainWindow.xaml w okienku Eksplorator rozwiązań, aby otworzyć projektanta.

Ważne części programu Visual Studio

Obsługa platformy WPF w programie Visual Studio ma pięć ważnych składników, z którymi będziesz korzystać podczas tworzenia aplikacji:

The important components of Visual Studio you should know when creating a WPF project for .NET

  1. Eksplorator rozwiązań

    Wszystkie pliki projektu, kod, okna, zasoby zostaną wyświetlone w tym okienku.

  2. Właściwości

    W tym okienku przedstawiono ustawienia właściwości, które można skonfigurować na podstawie wybranego elementu. Jeśli na przykład wybierzesz element z Eksplorator rozwiązań, zobaczysz ustawienia właściwości powiązane z plikiem. Jeśli wybierzesz obiekt w Projektant, zobaczysz ustawienia dla tego elementu.

  3. Przybornik

    Przybornik zawiera wszystkie kontrolki, które można dodać do formularza. Aby dodać kontrolkę do bieżącego formularza, kliknij dwukrotnie kontrolkę lub przeciągnij i upuść kontrolkę.

  4. Projektant XAML

    Jest to projektant dokumentu XAML. Jest to interaktywne i można przeciągać i upuszczać obiekty z przybornika. Wybierając i przenosząc elementy w projektancie, możesz wizualnie utworzyć interfejs użytkownika dla aplikacji.

    Gdy zarówno projektant, jak i edytor są widoczne, zmiany w jednym są odzwierciedlane w drugim. Po wybraniu elementów w projektancie w okienku Właściwości zostaną wyświetlone właściwości i atrybuty dotyczące tego obiektu.

  5. Edytor kodu XAML

    Jest to edytor kodu XAML dla dokumentu XAML. Edytor kodu XAML to sposób tworzenia interfejsu użytkownika ręcznie bez projektanta. Projektant może wnioskować wartości właściwości kontrolki po dodaniu kontrolki w projektancie. Edytor kodu XAML zapewnia znacznie większą kontrolę.

    Gdy zarówno projektant, jak i edytor są widoczne, zmiany w jednym są odzwierciedlane w drugim. Podczas nawigowania po karetce tekstu w edytorze kodu okienko Właściwości wyświetla właściwości i atrybuty dotyczące tego obiektu.

Sprawdzanie kodu XAML

Po utworzeniu projektu edytor kodu XAML jest widoczny z minimalną ilością kodu XAML do wyświetlenia okna. Jeśli edytor nie jest otwarty, kliknij dwukrotnie element MainWindow.xaml w Eksplorator rozwiązań. Powinien zostać wyświetlony kod XAML podobny do następującego przykładu:

<Window x:Class="Names.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Names"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

    </Grid>
</Window>

Przeanalizujmy ten kod XAML, aby lepiej go zrozumieć. XAML jest po prostu XML, który może być przetwarzany przez kompilatory używane przez WPF. Opisuje on interfejs użytkownika platformy WPF i wchodzi w interakcje z kodem platformy .NET. Aby zrozumieć język XAML, należy zapoznać się co najmniej z podstawami kodu XML.

Katalog główny <Window> dokumentu reprezentuje typ obiektu opisywanego przez plik XAML. Zadeklarowane są osiem atrybutów i zazwyczaj należą do trzech kategorii:

  • Przestrzenie nazw

    Przestrzeń nazw XML zapewnia strukturę xml, określając, jaką zawartość XML można zadeklarować w pliku.

    Główny xmlns atrybut importuje przestrzeń nazw XML dla całego pliku, a w tym przypadku mapuje na typy zadeklarowane przez WPF. Inne przestrzenie nazw XML deklarują prefiks i importują inne typy i obiekty dla pliku XAML. Na przykład xmlns:local przestrzeń nazw deklaruje prefiks i mapuje local je na obiekty zadeklarowane przez projekt, czyli te zadeklarowane w Names przestrzeni nazw kodu.

  • Atrybut x:Class

    Ten atrybut mapuje typ <Window> na typ zdefiniowany przez kod: MainWindow.xaml.cs lub MainWindow.xaml.vb , który jest klasą Names.MainWindow .

  • Atrybut Title

    Każdy atrybut normalny zadeklarowany w obiekcie XAML ustawia właściwość tego obiektu. W tym przypadku Title atrybut ustawia Window.Title właściwość .

Zmienianie okna

Najpierw uruchom projekt i wyświetl domyślne dane wyjściowe. Zobaczysz wyskakujące okno bez żadnych kontrolek i tytuł MainWindow:

A blank WPF app

W naszej przykładowej aplikacji to okno jest zbyt duże, a pasek tytułu nie jest opisowy. Zmień tytuł i rozmiar okna, zmieniając odpowiednie atrybuty w języku XAML na następujące wartości:

<Window x:Class="Names.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Names"
        mc:Ignorable="d"
        Title="Names" Height="180" Width="260">
    <Grid>
        
    </Grid>
</Window>

Przygotowywanie układu

WPF zapewnia zaawansowany system układu z wieloma różnymi kontrolkami układu. Kontrolki układu ułatwiają umieszczanie i ustawianie rozmiaru kontrolek podrzędnych, a nawet mogą to zrobić automatycznie. Domyślna kontrolka układu udostępniona w tym kodzie XAML to kontrolka <Grid> .

Kontrolka Grid umożliwia definiowanie wierszy i kolumn, podobnie jak tabela, oraz umieszczanie kontrolek w granicach określonej kombinacji wierszy i kolumn. Możesz mieć dowolną liczbę kontrolek podrzędnych lub innych kontrolek układu dodanych do elementu Grid. Można na przykład umieścić inną Grid kontrolkę w określonej kombinacji wierszy i kolumn, a następnie Grid zdefiniować więcej wierszy i kolumn oraz mieć własne elementy podrzędne.

Kontrolka <Grid> definiuje wiersze i kolumny, w których będą używane kontrolki. Siatka zawsze ma zadeklarowany pojedynczy wiersz i kolumnę, co oznacza, że siatka domyślnie jest pojedynczą komórką. To naprawdę nie daje dużo elastyczności w umieszczaniu kontrolek.

Przed dodaniem nowych wierszy i kolumn dodaj nowy atrybut do <Grid> elementu : Margin="10". Spowoduje to zaostrzeniu siatki z okna i sprawia, że wygląda trochę ładniej.

Następnie zdefiniuj dwa wiersze i dwie kolumny, dzieląc siatkę na cztery komórki:

<Grid Margin="10">
    
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    
</Grid>

Wybierz siatkę w edytorze kodu XAML lub projektancie XAML. Zobaczysz, że projektant XAML pokazuje każdy wiersz i kolumnę:

A WPF app with the margin set on a grid

Dodawanie pierwszej kontrolki

Teraz, gdy siatka została utworzona, możemy rozpocząć dodawanie do niej kontrolek. Najpierw zacznij od kontrolki etykiety. Utwórz nowy <Label> element wewnątrz <Grid> elementu po definicjach wierszy i kolumn i nadaj mu wartość ciągu :Names

<Grid Margin="10">

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Label>Names</Label>

</Grid>

Element <Label>Names</Label> definiuje zawartość Names. Niektóre kontrolki rozumieją sposób obsługi zawartości, inne nie. Zawartość kontrolki mapuje na Content właściwość . Ustawienie zawartości za pomocą składni atrybutu XAML, należy użyć następującego formatu: <Label Content="Names" />. Oba sposoby umożliwiają osiągnięcie tego samego celu, ustawiając zawartość etykiety, aby wyświetlić tekst Names.

Mamy jednak problem, etykieta zajmuje połowę okna, ponieważ został automatycznie przypisany do pierwszego wiersza i kolumny siatki. W naszym pierwszym wierszu nie potrzebujemy tyle miejsca, ponieważ będziemy używać tylko tego wiersza dla etykiety. Height Zmień atrybut pierwszego <RowDefinition> elementu z * na Auto. Wartość Auto automatycznie zmienia rozmiar wiersza siatki na rozmiar jego zawartości, w tym przypadku kontrolkę etykiety.

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>

Zwróć uwagę, że projektant pokazuje teraz etykietę zajmującą niewielką ilość dostępnej wysokości. Jest teraz więcej miejsca na następny wiersz do zajmowania. Większość kontrolek definiuje jakiś rodzaj wartości wysokości i szerokości, które powinny zajmować, które najlepiej dla nich wyglądają. Na przykład kontrolka etykiety ma wartość wysokości, która gwarantuje, że można go odczytać.

A WPF app with the margin set on a grid and a label control in the first row

Umieszczanie kontrolek

Porozmawiajmy o umieszczaniu kontrolek. Etykieta utworzona w powyższej sekcji została automatycznie umieszczona w wierszu 0 i kolumnie 0 siatki. Numerowanie wierszy i kolumn rozpoczyna się od 0 i zwiększa się o 1 dla każdego nowego wiersza lub kolumny. Kontrolka nie wie nic o siatce, a kontrolka nie definiuje żadnych właściwości do kontrolowania jej położenia w siatce. Kontrolka mogła zostać nawet umieszczona w innej kontrolce układu, która ma własny zestaw reguł definiujących sposób umieszczania kontrolek.

Jak poinformować kontrolkę o użyciu innego wiersza lub kolumny, gdy kontrolka nie zna siatki? Dołączone właściwości! Siatka korzysta z zaawansowanego systemu właściwości dostarczonego przez WPF. Siatka definiuje nowe właściwości, które kontrolki podrzędne mogą deklarować i używać. Właściwości nie istnieją w samej kontrolce, są one dołączone przez siatkę po dodaniu kontrolki do siatki.

Siatka definiuje dwie właściwości, aby określić położenie wiersza i kolumny kontrolki podrzędnej: Grid.Row i Grid.Column. Jeśli te właściwości zostaną pominięte w kontrolce, oznacza to, że mają wartości domyślne 0, dlatego kontrolka zostanie umieszczona w wierszu 0 i kolumnie 0 siatki. Spróbuj zmienić położenie kontrolki <Label> , ustawiając Grid.Column atrybut na 1:

<Label Grid.Column="1">Names</Label>

Zwróć uwagę, że etykieta została przeniesiona do drugiej kolumny. Możesz użyć Grid.Row właściwości i Grid.Column dołączonych, aby umieścić następne kontrolki, które utworzymy. Na razie jednak przywróć etykietę do kolumny 0.

Tworzenie pola listy nazw

Teraz, gdy siatka ma prawidłowy rozmiar i utworzoną etykietę, dodaj kontrolkę pola listy w wierszu poniżej etykiety. Pole listy będzie znajdować się w wierszu 1 i kolumnie 0. Nadamy również tej kontrolce lstNamesnazwę . Po nazwie kontrolki można odwoływać się do niej w kodzie. Nazwa jest przypisywana do kontrolki z atrybutem x:Name .

<Grid Margin="10">

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Label>Names</Label>
    <ListBox Grid.Row="1" x:Name="lstNames" />

</Grid>

Dodawanie pozostałych kontrolek

Ostatnie dwie kontrolki, które dodamy, to pole tekstowe i przycisk, którego użytkownik użyje do wprowadzenia nazwy w celu dodania do pola listy. Jednak zamiast próbować utworzyć więcej wierszy i kolumn dla siatki, umieścimy te kontrolki w kontrolce <StackPanel> układu.

Panel stosu różni się od siatki w sposobie umieszczania kontrolek. Gdy informujesz siatkę, w której mają znajdować się kontrolki z dołączonymi właściwościami Grid.Row i , Grid.Column panel stosu działa automatycznie, umieszczając pierwszą kontrolkę, a następnie umieszczając następną kontrolkę po niej, kontynuując do momentu umieszczenia wszystkich kontrolek. Ta kontrolka "stosuje" każdą kontrolkę poniżej drugiej.

Utwórz kontrolkę <StackPanel> po polu listy i umieść ją w kolumnie 1wiersza 1 siatki . Dodaj inny atrybut o nazwie Margin z wartością 5,0,0,0:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label>Names</Label>
<ListBox Grid.Row="1" x:Name="lstNames" />

<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
    
</StackPanel>

Atrybut Margin był wcześniej używany w siatce, ale umieszczamy tylko w jednej wartości 10. Teraz użyliśmy wartości 5,0,0,0 na panelu stosu. Margines jest typem Thickness i może interpretować obie wartości. Grubość definiuje przestrzeń wokół każdej strony prostokątnej ramki, lewej, górnej, prawej, dolnej, odpowiednio. Jeśli wartość marginesu jest pojedynczą wartością, używa tej wartości dla wszystkich czterech stron.

Następnie utwórz kontrolkę <TextBox> i <Button> w pliku <StackPanel>.

<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
    <TextBox x:Name="txtName" />
    <Button x:Name="btnAdd" Margin="0,5,0,0">Add Name</Button>
</StackPanel>

Układ okna został ukończony. Jednak nasza aplikacja nie ma w niej żadnej logiki, aby rzeczywiście była funkcjonalna. Następnie musimy podłączyć zdarzenia sterujące do kodu i pobrać aplikację, aby rzeczywiście coś zrobiła.

Dodawanie kodu dla zdarzenia Click

Utworzony <Button> obiekt zawiera Click zdarzenie, które jest zgłaszane, gdy użytkownik naciska przycisk. Możesz zasubskrybować to zdarzenie i dodać kod, aby dodać nazwę do pola listy. Podobnie jak w przypadku ustawiania właściwości kontrolki przez dodanie atrybutu XAML, możesz użyć atrybutu XAML do subskrybowania zdarzenia. Ustaw atrybut na ClickButtonAddName_Click

<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
    <TextBox x:Name="txtName" />
    <Button x:Name="btnAdd" Margin="0,5,0,0" Click="ButtonAddName_Click">Add Name</Button>
</StackPanel>

Teraz musisz wygenerować kod programu obsługi. Kliknij prawym przyciskiem myszy ButtonAddName_Click i wybierz polecenie Przejdź do definicji. Ta akcja generuje metodę w kodzie, która jest zgodna z wprowadzoną nazwą programu obsługi.

private void ButtonAddName_Click(object sender, RoutedEventArgs e)
{

}
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)

End Sub

Następnie dodaj następujący kod, aby wykonać trzy kroki:

  1. Upewnij się, że pole tekstowe zawiera nazwę.
  2. Sprawdź, czy nazwa wprowadzona w polu tekstowym jeszcze nie istnieje.
  3. Dodaj nazwę do pola listy.
private void ButtonAddName_Click(object sender, RoutedEventArgs e)
{
    if (!string.IsNullOrWhiteSpace(txtName.Text) && !lstNames.Items.Contains(txtName.Text))
    {
        lstNames.Items.Add(txtName.Text);
        txtName.Clear();
    }
}
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs)
    If Not String.IsNullOrWhiteSpace(txtName.Text) And Not lstNames.Items.Contains(txtName.Text) Then
        lstNames.Items.Add(txtName.Text)
        txtName.Clear()
    End If
End Sub

Uruchom aplikację

Teraz, gdy zdarzenie zostało zakodowane, możesz uruchomić aplikację, naciskając klawisz F5 lub wybierając polecenie Debuguj>rozpocznij debugowanie z menu. Zostanie wyświetlone okno i możesz wprowadzić nazwę w polu tekstowym, a następnie dodać je, klikając przycisk.

Running a Windows Presentation Foundation (WPF) for .NET app.

Następne kroki