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

W tym krótkim samouczku dowiesz się, jak utworzyć nową aplikację Windows Presentation Foundation (WPF) przy użyciu 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 po pulpicie dla platform .NET 6 i .NET 5 (w tym .NET Core 3.1) jest w trakcie budowy.

Ten samouczek zawiera informacje na temat wykonywania następujących czynności:

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

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

Finished sample app for WPF tutorial

Wymagania wstępne

Tworzenie aplikacji WPF

Pierwszym krokiem do utworzenia nowej aplikacji jest otwarcie 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 2019 for .NET.

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

  4. Na liście 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).

    Search for the WPF template in Visual Studio 2019 for .NET.

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

    1. W polu nazwa Project 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 2019 for .NET

  7. W oknie Dodatkowe informacje wybierz pozycję .NET 5.0 (bieżąca) dla elementu Target Framework. Wybierz przycisk Utwórz.

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

  1. Otwórz program Visual Studio.

  2. Wybierz pozycję Utwórz nowy projekt.

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

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

  4. Na liście 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. W oknie Konfigurowanie nowego projektu wykonaj następujące czynności:

    1. W polu nazwa Project 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. W oknie Dodatkowe informacje wybierz pozycję .NET 6.0 (długoterminowa obsługa) dla programu Target Framework. Wybierz przycisk Utwórz.

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

Po wygenerowaniu aplikacji Visual Studio powinno 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 Visual Studio

Obsługa platformy WPF w 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

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 są wyświetlane 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 Projektancie, 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 interaktywna 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 drugiej. 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 do projektanta. Edytor kodu XAML zapewnia o wiele większą kontrolę.

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

Badanie 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 to po prostu XML, który może być przetwarzany przez kompilatory używane przez WPF. Opisuje on interfejs użytkownika 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, jaka zawartość XML można zadeklarować w pliku.

    Atrybut główny xmlns 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 na obiekty zadeklarowane przez projekt, te zadeklarowane w Names przestrzeni nazw kodu.

  • Atrybut x:Class

    Ten atrybut mapuje <Window> 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

Platforma 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ślną kontrolką układu udostępnioną w tym kodzie XAML jest 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ą znajdować się 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". To powoduje, że siatka z okna jest nieco ładniejsza.

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

<Window x:Class="Names.LayoutStep2"
        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 Margin="10">
        
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

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

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ść Namesciągu :

<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 jest mapowania Content na właściwość . Ustawienie zawartości za pomocą składni atrybutu XAML, należy użyć następującego formatu: <Label Content="Names" />. Obie metody umożliwiają osiągnięcie tego samego celu, ustawiając zawartość etykiety w celu wyświetlenia tekstu Names.

Mamy jednak problem, ponieważ etykieta zajmuje połowę okna, ponieważ została automatycznie przypisana do pierwszego wiersza i kolumny siatki. W pierwszym wierszu nie potrzebujemy tego 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 kontrolki 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. Teraz jest 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 ją 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 umieszczania 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ą 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 jest umieszczana w wierszu 0 i kolumnie 0 siatki. Spróbuj zmienić położenie kontrolki <Label> , ustawiając atrybut na Grid.Column1:

<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 wiersza 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 wierszach 1 i kolumnach 0. Nadamy również tej kontrolce nazwę lstNames. 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 do dodania do pola listy. Jednak zamiast tworzyć 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 umieszczenia 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. "Stosy" każdej kontrolki 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 odstępy 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 mogła działać. Następnie musimy podłączyć zdarzenia sterujące do kodu i uzyskać aplikację, aby rzeczywiście coś zrobiła.

Dodawanie kodu dla zdarzenia click

Utworzony <Button> obiekt zawiera Click zdarzenie wywoływane po naciśnięciu przycisku przez użytkownika. Możesz subskrybować to zdarzenie i dodawać kod, aby dodać nazwę do pola listy. Podobnie jak właściwość w kontrolce przez dodanie atrybutu XAML, można użyć atrybutu XAML, aby zasubskrybować zdarzenie. 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 procedury 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ć te 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

Uruchamianie aplikacji

Teraz, gdy zdarzenie zostało zakodowane, możesz uruchomić aplikację, naciskając klawisz F5 lub wybierając pozycję DebugujRozpocznij> 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