Omówienie podsystemu WPF

Program Windows Presentation Foundation (WPF) umożliwia tworzenie aplikacji klienckich dla komputerów stacjonarnych dla systemu Windows z wizualnie oszałamiającymi środowiskami użytkownika.

Contoso Healthcare UI sample

Rdzeń WPF to niezależny od rozdzielczości i wektorowy aparat renderowania, który jest zbudowany w celu skorzystania z nowoczesnego sprzętu graficznego. WPF rozszerza rdzeń za pomocą kompleksowego zestawu funkcji tworzenia aplikacji, które obejmują extensible Application Markup Language (XAML), kontrolki, powiązanie danych, układ, grafiki 2D i 3D, animacje, style, szablony, dokumenty, multimedia, tekst i typografia. Struktura WPF jest częścią platformy .NET, co umożliwia tworzenie aplikacji zawierających inne elementy interfejsu API platformy .NET.

To omówienie jest przeznaczone dla nowych użytkowników, dlatego obejmuje najważniejsze możliwości i pojęcia dotyczące struktury WPF.

Program ze strukturą WPF

WPF istnieje jako podzbiór typów .NET, które są (w większości) znajdujące się w System.Windows przestrzeni nazw. Jeśli wcześniej utworzono aplikacje na platformie .NET przy użyciu technologii zarządzanych, takich jak ASP.NET i Windows Forms, podstawowe środowisko programowania WPF powinno być znane; Tworzy się wystąpienia klas, ustawia właściwości, metody wywoływania i obsługuje zdarzenia przy użyciu ulubionego języka programowania .NET, takiego jak C# lub Visual Basic.

WPF zawiera dodatkowe konstrukcje programistyczne, które zwiększają właściwości i zdarzenia: właściwości zależności i zdarzenia kierowane.

Znaczniki i plik codebehind

Struktura WPF umożliwia tworzenie aplikacji przy użyciu zarówno znaczników, jak i pliku codebehind, środowiska, które powinno być znane deweloperom ASP.NET. Na ogół używa się znaczników XAML do implementowania wyglądu aplikacji oraz zarządzanych języków programowania (plik codebehind) do implementowania ich zachowania. Rozdzielenie wyglądu od zachowania przynosi następujące korzyści:

  • Koszty programowania i konserwacji są mniejsze, ponieważ znaczniki specyficzne dla wyglądu nie są ściśle powiązane z kodem specyficznym dla zachowania.

  • Programowanie jest bardziej wydajne, ponieważ projektanci mogą implementować wygląd aplikacji jednocześnie z deweloperami, którzy implementują zachowanie aplikacji.

  • Uproszczona globalizacja i lokalizacja aplikacji WPF.

Znaczników

XAML to język znaczników oparty na języku XML, który deklaratywnie implementuje wygląd aplikacji. Zazwyczaj służy do tworzenia okien, okien dialogowych, stron i kontrolek użytkownika oraz wypełniania ich kontrolkami, kształtami i grafiką.

W poniższym przykładzie za pomocą języka XAML zaimplementowano wygląd okna zawierającego jeden przycisk:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Title="Window with Button"
    Width="250" Height="100">

  <!-- Add button to window -->
  <Button Name="button">Click Me!</Button>

</Window>

W szczególności ten kod XAML definiuje okno i przycisk przy użyciu Window odpowiednio elementów i Button . Każdy element jest skonfigurowany za pomocą atrybutów, takich jak atrybut Title elementu Window określający tekst na pasku tytułu okna. W czasie wykonywania struktura WPF konwertuje elementy i atrybuty zdefiniowane w znacznikach na wystąpienia klas WPF. Na przykład element Window jest konwertowany na wystąpienie klasy Window, której właściwość Title jest wartością atrybutu Title.

Na poniższej ilustracji przedstawiono interfejs użytkownika zdefiniowany przez kod XAML w poprzednim przykładzie:

A window that contains a button

Ponieważ język XAML jest oparty na kodzie XML, interfejs użytkownika, który jest komponowany z nim, jest składany w hierarchii zagnieżdżonych elementów nazywanych drzewem elementów. Drzewo elementów zapewnia logiczny i intuicyjny sposób tworzenia interfejsów użytkownika i zarządzania nimi.

Plik codebehind

Głównym zachowaniem aplikacji jest zaimplementowanie funkcji, która reaguje na interakcje użytkowników, w tym obsługę zdarzeń (na przykład kliknięcie menu, paska narzędzi lub przycisku) oraz wywołanie logiki biznesowej i logiki dostępu do danych w odpowiedzi. W ramach struktury WPF to zachowanie jest implementowane w kodzie skojarzonym ze znacznikami. Ten typ kodu nosi nazwę pliku codebehind. W poniższym przykładzie przedstawiono zaktualizowany znacznik z poprzedniego przykładu i plik codebehind:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.AWindow"
    Title="Window with Button"
    Width="250" Height="100">

  <!-- Add button to window -->
  <Button Name="button" Click="button_Click">Click Me!</Button>

</Window>
using System.Windows; // Window, RoutedEventArgs, MessageBox

namespace SDKSample
{
    public partial class AWindow : Window
    {
        public AWindow()
        {
            // InitializeComponent call is required to merge the UI
            // that is defined in markup with this class, including  
            // setting properties and registering event handlers
            InitializeComponent();
        }

        void button_Click(object sender, RoutedEventArgs e)
        {
            // Show message box when button is clicked.
            MessageBox.Show("Hello, Windows Presentation Foundation!");
        }
    }
}
Namespace SDKSample

    Partial Public Class AWindow
        Inherits System.Windows.Window

        Public Sub New()

            ' InitializeComponent call is required to merge the UI
            ' that is defined in markup with this class, including  
            ' setting properties and registering event handlers
            InitializeComponent()

        End Sub

        Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

            ' Show message box when button is clicked.
            MessageBox.Show("Hello, Windows Presentation Foundation!")

        End Sub

    End Class

End Namespace

W tym przykładzie kod-behind implementuje klasę pochodzącą z Window klasy . Atrybut x:Class jest używany do skojarzenia znaczników z klasą za pomocą kodu. Element InitializeComponent jest wywoływany z konstruktora klasy pliku codebehind w celu scalenia interfejsu użytkownika zdefiniowanego w znacznikach z klasą pliku codebehind. (InitializeComponent jest generowany dla Ciebie podczas kompilowania aplikacji, dlatego nie trzeba jej implementować ręcznie). Kombinacja i InitializeComponent upewnienie x:Class się, że implementacja jest poprawnie zainicjowana za każdym razem, gdy zostanie utworzona. Klasa za kodem implementuje również procedurę obsługi zdarzeń dla zdarzenia przycisku Click . Po kliknięciu przycisku program obsługi zdarzeń wyświetla pole komunikatu, wywołując metodę System.Windows.MessageBox.Show .

Na poniższej ilustracji przedstawiono rezultat kliknięcia przycisku:

A MessageBox

Kontrolki

Środowiska użytkownika dostarczane przez model aplikacji są skonstruowanymi kontrolkami. W WPF kontrolka jest terminem parasolowym, który ma zastosowanie do kategorii klas WPF, które są hostowane w oknie lub na stronie, mają interfejs użytkownika i implementują pewne zachowanie.

Aby uzyskać więcej informacji, zobacz Kontrolki.

Kontrolki WPF według funkcji

Poniżej wymieniono wbudowane kontrolki WPF:

Dane wejściowe i polecenia

Kontrolki najczęściej wykrywają dane wejściowe użytkownika i reagują na nie. System wejściowy WPF używa zarówno zdarzeń bezpośrednich, jak i kierowanych do obsługi wprowadzania tekstu, zarządzania fokusem i pozycjonowania myszy.

Aplikacje często mają złożone wymagania dotyczące danych wejściowych. WPF udostępnia system poleceń, który oddziela akcje wejściowe użytkownika od kodu, który odpowiada na te akcje.

Układ

Podczas tworzenia interfejsu użytkownika rozmieszcza się kontrolki według lokalizacji i rozmiaru, aby utworzyć układ. Kluczowym wymaganiem dla każdego układu jest dostosowanie się do zmian rozmiaru okna i ustawień wyświetlania. Zamiast wymuszać pisanie kodu w celu dostosowania układu w tych okolicznościach, struktura WPF zapewnia najwyższej klasy, rozszerzalny system układu.

Podstawą systemu układu jest pozycjonowanie względne, które zwiększa możliwość adaptacji do zmieniających się warunków okna i wyświetlania. Ponadto system układów zarządza negocjacjami między kontrolkami w celu określenia układu. Negocjacja jest procesem dwuetapowym: najpierw kontrolka informuje rodzica, jakiej lokalizacji i rozmiaru wymaga; po drugie, element nadrzędny informuje kontrolkę, jaką przestrzeń może mieć.

System układu jest uwidaczniany dla kontrolek podrzędnych za pomocą podstawowych klas WPF. Na potrzeby typowych układów, takich jak siatki, umieszczanie na stosie i dokowanie, struktura WPF zawiera kilka kontrolek układu:

  • Canvas: Kontrolki podrzędne mają własny układ.

  • DockPanel: Kontrolki podrzędne są wyrównane do krawędzi panelu.

  • Grid: Kontrolki podrzędne są pozycjonowane według wierszy i kolumn.

  • StackPanel: Kontrolki podrzędne są umieszczane na stosie pionowo lub poziomo.

  • VirtualizingStackPanel: Kontrolki podrzędne są wirtualizowane i rozmieszczane w jednym wierszu o orientacji poziomej lub pionowej.

  • WrapPanel: Kontrolki podrzędne są umieszczone w kolejności od lewej do prawej i opakowane do następnego wiersza, gdy w bieżącym wierszu znajduje się więcej kontrolek, niż pozwala na to spacja.

W poniższym przykładzie użyto elementu DockPanel, aby utworzyć układ kilku kontrolek TextBox:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.LayoutWindow"
    Title="Layout with the DockPanel" Height="143" Width="319">
  
  <!--DockPanel to layout four text boxes--> 
  <DockPanel>
    <TextBox DockPanel.Dock="Top">Dock = "Top"</TextBox>
    <TextBox DockPanel.Dock="Bottom">Dock = "Bottom"</TextBox>
    <TextBox DockPanel.Dock="Left">Dock = "Left"</TextBox>
    <TextBox Background="White">This TextBox "fills" the remaining space.</TextBox>
  </DockPanel>

</Window>

Element DockPanel umożliwia kontrolkom podrzędnym TextBox informowanie o sposobie ich rozmieszczenia. W tym celu element DockPanel implementuje właściwość dołączoną Dock uwidocznioną dla kontrolek podrzędnych, aby umożliwić każdej z nich określenie stylu dokowania.

Uwaga

Właściwość zaimplementowana przez kontrolkę nadrzędną do użycia przez kontrolki podrzędne to konstrukcja WPF nazywana właściwością dołączoną.

Na poniższej ilustracji przedstawiono wynik działania znaczników XAML z poprzedniego przykładu:

DockPanel page

Powiązanie danych

Większość aplikacji tworzy się w celu zapewnienia użytkownikom środków do wyświetlania i edytowania danych. W przypadku aplikacji WPF praca przechowywania i uzyskiwania dostępu do danych jest już zapewniana przez technologie, takie jak SQL Server i ADO .NET. Po uzyskaniu dostępu do danych i załadowaniu ich do obiektów zarządzanych aplikacji rozpoczyna się ciężka praca dla aplikacji WPF. Zasadniczo obejmuje ona dwie rzeczy:

  1. Kopiowanie danych z obiektów zarządzanych do kontrolek, w których można wyświetlać i edytować dane.

  2. Zapewnianie, że zmiany danych wprowadzone przy użyciu kontrolek zostaną skopiowane z powrotem do obiektów zarządzanych.

Aby uprościć tworzenie aplikacji, platforma WPF udostępnia aparat powiązania danych, który umożliwia automatyczne wykonywanie tych kroków. Podstawową jednostką aparatu powiązania danych jest klasa Binding, której zadaniem jest powiązanie kontrolki (obiektu docelowego powiązania) z obiektem danych (obiektem źródłowym powiązania). Tę relację pokazano na poniższej ilustracji:

Basic data binding diagram

W następnym przykładzie pokazano, jak powiązać obiekt z TextBox wystąpieniem obiektu niestandardowego Person . Implementacja jest pokazana Person w następującym kodzie:

Namespace SDKSample

    Class Person

        Private _name As String = "No Name"

        Public Property Name() As String
            Get
                Return _name
            End Get
            Set(ByVal value As String)
                _name = value
            End Set
        End Property

    End Class

End Namespace
namespace SDKSample
{
    class Person
    {
        string name = "No Name";

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
}

Poniższy znacznik wiąże element TextBox z wystąpieniem obiektu niestandardowego Person :

 <Window
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="SDKSample.DataBindingWindow">

   <!-- Bind the TextBox to the data source (TextBox.Text to Person.Name) -->
   <TextBox Name="personNameTextBox" Text="{Binding Path=Name}" />

 </Window>
Imports System.Windows ' Window

Namespace SDKSample

    Partial Public Class DataBindingWindow
        Inherits Window

        Public Sub New()
            InitializeComponent()

            ' Create Person data source
            Dim person As Person = New Person()

            ' Make data source available for binding
            Me.DataContext = person

        End Sub

    End Class

End Namespace
using System.Windows; // Window

namespace SDKSample
{
    public partial class DataBindingWindow : Window
    {
        public DataBindingWindow()
        {
            InitializeComponent();

            // Create Person data source
            Person person = new Person();

            // Make data source available for binding
            this.DataContext = person;
        }
    }
}

W tym przykładzie klasa jest utworzona Person w kodzie i jest ustawiana jako kontekst danych dla klasy DataBindingWindow. W adiustacji Text właściwość TextBox jest powiązana z właściwością Person.Name (przy użyciu składni XAML "{Binding ... }"). Ten kod XAML informuje WPF o powiązaniu kontrolki TextBoxPerson z obiektem przechowywanym DataContext we właściwości okna.

Aparat powiązania danych WPF zapewnia dodatkową obsługę, która obejmuje walidację, sortowanie, filtrowanie i grupowanie. Ponadto powiązanie danych obsługuje używanie szablonów danych do tworzenia niestandardowego interfejsu użytkownika dla powiązanych danych, gdy interfejs użytkownika wyświetlany przez standardowe kontrolki WPF nie jest odpowiedni.

Aby uzyskać więcej informacji, zobacz Omówienie powiązania danych.

Karty graficzne

WPF oferuje rozbudowany, skalowalny i elastyczny zestaw funkcji graficznych, które mają następujące korzyści:

  • Grafika niezależna od rozdzielczości i niezależna od urządzenia. Podstawową jednostką miary w systemie graficznym WPF jest niezależny od urządzenia piksel, który jest 1/96 cala, niezależnie od rzeczywistej rozdzielczości ekranu i stanowi podstawę renderowania niezależnego od rozdzielczości i niezależnego od urządzenia. Każdy piksel niezależny od urządzenia jest automatycznie skalowany w celu dopasowania do ustawienia liczby punktów na cal (dpi) systemu, na który jest renderowany.

  • Zwiększona precyzja. System współrzędnych WPF jest mierzony przy użyciu liczb zmiennoprzecinkowych o podwójnej (a nie pojedynczej) precyzji. Przekształcenia i wartości nieprzezroczystości również są wyrażane z podwójną precyzją. Struktura WPF obsługuje również szeroką gamę kolorów (scRGB) i zapewnia zintegrowaną obsługę zarządzania danymi wejściowymi z różnych przestrzeni kolorów.

  • Obsługa zaawansowanej grafiki i animacji. WPF upraszcza programowanie grafiki, zarządzając scenami animacji; Nie ma potrzeby martwić się o przetwarzanie scen, pętle renderowania i interpolację dwuliniową. Ponadto struktura WPF zapewnia obsługę testowania trafień i pełną obsługę składania alfa.

  • Przyspieszanie sprzętowe. System graficzny WPF wykorzystuje sprzęt graficzny, aby zminimalizować użycie procesora CPU.

Kształty 2D

WPF udostępnia bibliotekę typowych kształtów 2D narysowanych wektorowo, takich jak prostokąty i wielokropki, które przedstawiono na poniższej ilustracji:

Ellipses and rectangles

Interesującą możliwością kształtów jest to, że nie są one przeznaczone tylko do wyświetlania; kształty implementują wiele funkcji, których oczekujesz od kontrolek, w tym klawiatury i myszy. W poniższym przykładzie pokazano MouseUp zdarzenie obsługiwanego Ellipse elementu:

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.EllipseEventHandlingWindow"
    Title="Click the Ellipse">
    <Ellipse Name="clickableEllipse" Fill="Blue" MouseUp="clickableEllipse_MouseUp" />
</Window>
Imports System.Windows ' Window, MessageBox
Imports System.Windows.Input ' MouseButtonEventArgs

Namespace SDKSample

    Public Class EllipseEventHandlingWindow
        Inherits Window

        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub clickableEllipse_MouseUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
            MessageBox.Show("You clicked the ellipse!")
        End Sub

    End Class

End Namespace
using System.Windows; // Window, MessageBox
using System.Windows.Input; // MouseButtonEventHandler

namespace SDKSample
{
    public partial class EllipseEventHandlingWindow : Window
    {
        public EllipseEventHandlingWindow()
        {
            InitializeComponent();
        }

        void clickableEllipse_MouseUp(object sender, MouseButtonEventArgs e)
        {
            // Display a message
            MessageBox.Show("You clicked the ellipse!");
        }
    }
}

Na poniższej ilustracji pokazano, co zostało wygenerowane przez poprzedni kod:

A window with the text

Aby uzyskać więcej informacji, zobacz Kształty i podstawowy rysunek w omówieniu WPF.

Geometrie 2D

Kształty 2D dostarczane przez strukturę WPF obejmują standardowy zestaw kształtów podstawowych. Jednak może być konieczne utworzenie niestandardowych kształtów w celu ułatwienia projektowania dostosowanego interfejsu użytkownika. W tym celu WPF zapewnia geometrie. Na poniższej ilustracji przedstawiono użycie geometrii do utworzenia niestandardowego kształtu, który może być rysowany bezpośrednio, używany jako szczotka lub używany do przycinania innych kształtów i kontrolek.

Path obiekty mogą służyć do rysowania zamkniętych lub otwartych kształtów, wielu kształtów, a nawet kształtów zakrzywionych.

Geometry obiekty mogą służyć do wycinania, testowania trafień i renderowania danych graficznych 2D.

Various uses of a path

Aby uzyskać więcej informacji, zobacz Omówienie geometrii.

Efekty 2D

Podzestaw możliwości 2D struktury WPF obejmuje efekty wizualne, takie jak gradienty, mapy bitowe, rysunki, malowanie wideo, rotacja, skalowanie i pochylanie. Wszystkie te czynności są osiągane za pomocą pędzli; Na poniższej ilustracji przedstawiono kilka przykładów:

Illustration of different brushes

Aby uzyskać więcej informacji, zobacz Omówienie pędzli WPF.

Renderowanie 3D

Struktura WPF obejmuje również możliwości renderowania 3D, które integrują się z grafiką 2D, aby umożliwić tworzenie bardziej ekscytujących i interesujących interfejsów użytkownika. Na przykład na poniższej ilustracji przedstawiono obrazy 2D renderowane na kształty 3D:

Visual3D sample screen shot

Aby uzyskać więcej informacji, zobacz Omówienie grafiki 3D.

Animacja

Obsługa animacji WPF umożliwia stosowanie efektów powiększania, wstrząsania, obracania i zanikania dla kontrolek w celu tworzenia interesujących przejść między stronami i nie tylko. Większość klas WPF można animować, nawet klasy niestandardowe. Na poniższej ilustracji przedstawiono prostą animację w działaniu:

Images of an animated cube

Aby uzyskać więcej informacji, zobacz Omówienie animacji.

Multimedia

Jednym ze sposobów przekazywania bogatych treści jest wykorzystanie mediów audiowizualnego. Platforma WPF zapewnia specjalną obsługę obrazów, wideo i audio.

Obrazy

Obrazy są typowe dla większości aplikacji, a WPF oferuje kilka sposobów ich używania. Na poniższej ilustracji przedstawiono interfejs użytkownika z polem listy zawierającym obrazy miniatur. Po wybraniu miniatury obraz jest wyświetlany w pełnym rozmiarze.

Thumbnail images and a full-size image

Aby uzyskać więcej informacji, zobacz Obrazowanie — omówienie.

Wideo i dźwięk

Kontrolka MediaElement jest w stanie odtwarzać zarówno wideo, jak i audio, i jest wystarczająco elastyczna, aby być podstawą niestandardowego odtwarzacza multimedialnego. Następujące znaczniki XAML implementują odtwarzacz multimedialny:

<MediaElement 
  Name="myMediaElement" 
  Source="media/wpf.wmv" 
  LoadedBehavior="Manual" 
  Width="350" Height="250" />

W oknie na poniższej ilustracji przedstawiono akcję kontrolki MediaElement :

A MediaElement control with audio and video

Aby uzyskać więcej informacji, zobacz Grafika i multimedia.

Tekst i typografia

Aby ułatwić renderowanie tekstu wysokiej jakości, platforma WPF oferuje następujące funkcje:

  • Obsługa czcionek OpenType.

  • Ulepszenia technologii ClearType.

  • Wysoka wydajność wykorzystująca przyspieszanie sprzętowe.

  • Integracja tekstu z multimediami, grafiką i animacją.

  • Obsługa czcionek międzynarodowych i mechanizmy awaryjne.

W ramach pokazu integracji tekstu z grafiką na poniższej ilustracji przedstawiono zastosowanie dekoracji tekstu:

Text with various text decorations

Aby uzyskać więcej informacji, zobacz Typografia w strukturze Windows Presentation Foundation.

Dostosowywanie aplikacji WPF

Do tego momentu przedstawiono podstawowe bloki konstrukcyjne WPF do tworzenia aplikacji. Model aplikacji służy do hostowania i dostarczania zawartości aplikacji, która składa się głównie z kontrolek. Aby uprościć rozmieszczenie kontrolek w interfejsie użytkownika i upewnić się, że układ jest utrzymywany w obliczu zmian rozmiaru okna i ustawień wyświetlania, należy użyć systemu układu WPF. Ponieważ większość aplikacji umożliwia użytkownikom interakcję z danymi, należy użyć powiązania danych, aby zmniejszyć pracę integracji interfejsu użytkownika z danymi. Aby poprawić wygląd wizualny aplikacji, użyj kompleksowego zakresu grafiki, animacji i obsługi multimediów dostarczanego przez strukturę WPF.

Często jednak podstawy nie są wystarczające do tworzenia i zarządzania naprawdę odrębnym i wizualnie oszałamiającym środowiskiem użytkownika. Standardowe kontrolki WPF mogą nie integrować się z pożądanym wyglądem aplikacji. Dane mogą nie być wyświetlane w najbardziej efektywny sposób. Ogólne środowisko użytkownika aplikacji może nie być dostosowane do domyślnego wyglądu i sposobu działania motywów systemu Windows. Na wiele sposobów technologia prezentacji wymaga rozszerzalności wizualnej, podobnie jak w przypadku każdego innego typu rozszerzalności.

Z tego powodu platforma WPF oferuje różne mechanizmy tworzenia unikatowych środowisk użytkownika, w tym bogaty con tryb namiotu l dla kontrolek, wyzwalaczy, kontrolek i szablonów danych, stylów, zasobów interfejsu użytkownika oraz motywów i skórek.

Con tryb namiotu l

Głównym celem większości kontrolek WPF jest wyświetlanie zawartości. W strukturze WPF typ i liczbę elementów, które mogą stanowić zawartość kontrolki, określa się jako model zawartości kontrolki. Niektóre kontrolki mogą zawierać pojedynczy element i typ zawartości; na przykład zawartość obiektu TextBox jest wartością ciągu przypisaną do Text właściwości . Poniższy przykład ustawia zawartość elementu TextBox:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.TextBoxContentWindow"
    Title="TextBox Content">

    <TextBox Text="This is the content of a TextBox." />
</Window>

Na poniższej ilustracji przedstawiono wynik:

A TextBox control that contains text

Inne kontrolki mogą jednak zawierać wiele elementów różnych typów zawartości; zawartość Buttonobiektu , określona przez Content właściwość, może zawierać różne elementy, w tym kontrolki układu, tekst, obrazy i kształty. Poniższy przykład przedstawia Button zawartość zawierającą DockPanelelement , a Label, , Borderi MediaElement:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.ButtonContentWindow"
    Title="Button Content">

  <Button Margin="20">
    <!-- Button Content -->
    <DockPanel Width="200" Height="180">
      <Label DockPanel.Dock="Top" HorizontalAlignment="Center">Click Me!</Label>
      <Border Background="Black" BorderBrush="Yellow" BorderThickness="2"
        CornerRadius="2" Margin="5">
        <MediaElement Source="media/wpf.wmv" Stretch="Fill" />
      </Border>
    </DockPanel>
  </Button>
</Window>

Na poniższej ilustracji przedstawiono zawartość tego przycisku:

A button that contains multiple types of content

Aby uzyskać więcej informacji na temat rodzajów zawartości obsługiwanej przez różne kontrolki, zobacz Model zawartości WPF.

Wyzwalacze

Chociaż głównym zadaniem znaczników XAML jest implementowanie wyglądu aplikacji, języka XAML można również używać do implementowania niektórych aspektów zachowania aplikacji. Jednym z przykładów jest użycie wyzwalaczy w celu zmiany wyglądu aplikacji na podstawie interakcji użytkownika. Aby uzyskać więcej informacji, zobacz Style i szablony.

Szablony kontrolek

Domyślne interfejsy użytkownika kontrolek WPF są zwykle konstruowane z innych kontrolek i kształtów. Na przykład element Button składa się z kontrolek ButtonChrome i ContentPresenter. Element ButtonChrome zapewnia standardowy wygląd przycisku, a element ContentPresenter wyświetla zawartość przycisku określoną przez właściwość Content.

Czasami domyślny wygląd kontrolki może być niespójny z ogólnym wyglądem aplikacji. W takim przypadku można użyć elementu ControlTemplate, aby zmienić wygląd interfejsu użytkownika kontrolki bez zmiany jego zawartości i zachowania.

W poniższym przykładzie pokazano, jak zmienić wygląd obiektu Button przy użyciu elementu ControlTemplate:

<Window 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.ControlTemplateButtonWindow"
  Title="Button with Control Template" Height="158" Width="290">

  <!-- Button using an ellipse -->
  <Button Content="Click Me!" Click="button_Click">
    <Button.Template>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid Margin="5">
          <Ellipse Stroke="DarkBlue" StrokeThickness="2">
            <Ellipse.Fill>
              <RadialGradientBrush Center="0.3,0.2" RadiusX="0.5" RadiusY="0.5">
                <GradientStop Color="Azure" Offset="0.1" />
                <GradientStop Color="CornflowerBlue" Offset="1.1" />
              </RadialGradientBrush>
            </Ellipse.Fill>
          </Ellipse>
          <ContentPresenter Name="content" HorizontalAlignment="Center" 
            VerticalAlignment="Center"/>
        </Grid>
      </ControlTemplate>
    </Button.Template>

  </Button>

</Window>
using System.Windows; // Window, RoutedEventArgs, MessageBox

namespace SDKSample
{
    public partial class ControlTemplateButtonWindow : Window
    {
        public ControlTemplateButtonWindow()
        {
            InitializeComponent();
        }

        void button_Click(object sender, RoutedEventArgs e)
        {
            // Show message box when button is clicked
            MessageBox.Show("Hello, Windows Presentation Foundation!");
        }
    }
}
Imports System.Windows ' Window, RoutedEventArgs, MessageBox

Namespace SDKSample

    Public Class ControlTemplateButtonWindow
        Inherits Window

        Public Sub New()

            InitializeComponent()

        End Sub

        Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            MessageBox.Show("Hello, Windows Presentation Foundation!")
        End Sub

    End Class

End Namespace

W tym przykładzie domyślny interfejs użytkownika przycisku został zastąpiony symbolem Ellipse , który ma ciemnoniebieskie obramowanie i jest wypełniany przy użyciu elementu RadialGradientBrush. Kontrolka ContentPresenter wyświetla zawartość elementu Button" Kliknij mnie!" Po kliknięciu ButtonClick zdarzenia jest nadal zgłaszane w ramach domyślnego Button zachowania kontrolki. Wynik przedstawiono na poniższej ilustracji:

An elliptical button and a second window

Szablony danych

Podczas gdy szablon kontrolki pozwala określić jej wygląd, szablon danych umożliwia określenie wyglądu zawartości kontrolki. Szablony danych są często używane do ulepszania sposobu wyświetlania powiązanych danych. Na poniższej ilustracji przedstawiono domyślny wygląd elementu ListBox powiązanego z kolekcją obiektów Task, gdzie każde zadanie ma nazwę, opis i priorytet:

A list box with the default appearance

Wygląd domyślny to wygląd, jakiego można oczekiwać od elementu ListBox. Jednak wygląd domyślny każdego zadania zawiera tylko nazwę zadania. Aby wyświetlić nazwę, opis i priorytet zadania, wygląd domyślny powiązanych elementów listy kontrolki ListBox należy zmienić przy użyciu elementu DataTemplate. Poniższy kod XAML definiuje taki DataTemplatekod , który jest stosowany do każdego zadania przy użyciu atrybutu ItemTemplate :

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.DataTemplateWindow"
  Title="With a Data Template">
  <Window.Resources>
    <!-- Data Template (applied to each bound task item in the task collection) -->
    <DataTemplate x:Key="myTaskTemplate">
      <Border Name="border" BorderBrush="DarkSlateBlue" BorderThickness="2"
        CornerRadius="2" Padding="5" Margin="5">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <TextBlock Grid.Row="0" Grid.Column="0" Padding="0,0,5,0" Text="Task Name:"/>
          <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}"/>
          <TextBlock Grid.Row="1" Grid.Column="0" Padding="0,0,5,0" Text="Description:"/>
          <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
          <TextBlock Grid.Row="2" Grid.Column="0" Padding="0,0,5,0" Text="Priority:"/>
          <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
        </Grid>
      </Border>
    </DataTemplate>
  </Window.Resources>

  <!-- UI -->
  <DockPanel>
    <!-- Title -->
    <Label DockPanel.Dock="Top" FontSize="18" Margin="5" Content="My Task List:"/>

    <!-- Data template is specified by the ItemTemplate attribute -->
    <ListBox
      ItemsSource="{Binding}"
      ItemTemplate="{StaticResource myTaskTemplate}"
      HorizontalContentAlignment="Stretch"
      IsSynchronizedWithCurrentItem="True"
      Margin="5,0,5,5" />

 </DockPanel>
</Window>

Na poniższej ilustracji przedstawiono efekt tego kodu:

List box that uses a data template

Należy pamiętać, że ListBox obiekt zachował zachowanie i ogólny wygląd; zmienił się tylko wygląd zawartości wyświetlanej przez pole listy.

Aby uzyskać więcej informacji, zobacz Omówienie tworzenia szablonów danych.

Style

Style umożliwiają deweloperom i projektantom standaryzację określonego wyglądu produktu. Struktura WPF zapewnia silny model stylu, którego podstawą jest element Style. Poniższy przykład tworzy styl, który ustawia kolor tła dla każdego Button elementu w oknie na wartość Orange:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.StyleWindow"
    Title="Styles">
    
    <Window.Resources>
        <!-- Style that will be applied to all buttons for this window -->
        <Style TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Orange" />
            <Setter Property="BorderBrush" Value="Crimson" />
            <Setter Property="FontSize" Value="20" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Margin" Value="5" />
        </Style>
    </Window.Resources>
    <StackPanel>

        <!-- This button will have the style applied to it -->
        <Button>Click Me!</Button>

        <!-- This label will not have the style applied to it -->
        <Label>Don't Click Me!</Label>

        <!-- This button will have the style applied to it -->
        <Button>Click Me!</Button>
        
    </StackPanel>
</Window>

Ponieważ ten styl jest przeznaczony dla wszystkich kontrolek Button, styl jest automatycznie stosowany do wszystkich przycisków w oknie, jak pokazano na poniższej ilustracji:

Two orange buttons

Aby uzyskać więcej informacji, zobacz Style i szablony.

Zasoby

Kontrolki w aplikacji powinny mieć taki sam wygląd, który może zawierać dowolne elementy od czcionek i kolorów tła do szablonów kontrolek, szablonów danych i stylów. Obsługa struktury WPF dla zasobów interfejsu użytkownika umożliwia hermetyzowanie tych zasobów w jednej lokalizacji w celu ponownego użycia.

W poniższym przykładzie zdefiniowano wspólny kolor tła, który jest współużytkowany przez elementy Button i Label:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.ResourcesWindow"
    Title="Resources Window">

  <!-- Define window-scoped background color resource -->
  <Window.Resources>
    <SolidColorBrush x:Key="defaultBackground" Color="Red" />
  </Window.Resources>

  <!-- Button background is defined by window-scoped resource -->
  <Button Background="{StaticResource defaultBackground}">One Button</Button>

  <!-- Label background is defined by window-scoped resource -->
  <Label Background="{StaticResource defaultBackground}">One Label</Label>
</Window>

W tym przykładzie zaimplementowany jest zasób koloru tła przy użyciu Window.Resources elementu właściwości. Ten zasób jest dostępny dla wszystkich elementów podrzędnych obiektu Window. Istnieją różne zakresy zasobów, w tym następujące, wymienione w kolejności, w której zostały rozwiązane:

  1. Pojedyncza kontrolka (przy użyciu właściwości dziedziczonej System.Windows.FrameworkElement.Resources ).

  2. A Window lub Page (również przy użyciu dziedziczonej System.Windows.FrameworkElement.Resources właściwości).

  3. An Application (przy użyciu System.Windows.Application.Resources właściwości ).

Różnorodność zakresów zapewnia elastyczność w zakresie sposobu definiowania i udostępniania zasobów.

Alternatywą dla bezpośredniego kojarzenia zasobów z określonym zakresem jest spakowanie jednego lub większej liczby zasobów przy użyciu oddzielnej ResourceDictionary , do której można odwoływać się w innych częściach aplikacji. Na przykład w poniższym przykładzie zdefiniowano domyślny kolor tła w słowniku zasobów:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <!-- Define background color resource -->
  <SolidColorBrush x:Key="defaultBackground" Color="Red" />

  <!-- Define other resources -->
</ResourceDictionary>

Poniższy przykład odwołuje się do słownika zasobów zdefiniowanego w poprzednim przykładzie, aby był udostępniany w aplikacji:

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App">

  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="BackgroundColorResources.xaml"/>
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

Zasoby i słowniki zasobów są podstawą obsługi WPF dla motywów i skórek.

Aby uzyskać więcej informacji, zobacz Zasoby.

Kontrolki niestandardowe

Mimo że struktura WPF zapewnia hosta obsługi dostosowywania, mogą wystąpić sytuacje, w których istniejące kontrolki WPF nie spełniają wymagań aplikacji lub jej użytkowników. Może się to zdarzyć w następujących przypadkach:

  • Nie można utworzyć wymaganego interfejsu użytkownika przez dostosowanie wyglądu i sposobu działania istniejących implementacji WPF.

  • Wymagane zachowanie nie jest obsługiwane (lub nie jest łatwo obsługiwane) przez istniejące implementacje WPF.

Jednak na tym etapie można skorzystać z jednego z trzech modeli WPF, aby utworzyć nową kontrolkę. Każdy model jest przeznaczony dla określonego scenariusza i wymaga niestandardowej kontrolki pochodzącej z określonej klasy bazowej WPF. Poniżej wymieniono t trzy modele:

  • Model kontroli użytkownika. Kontrolka niestandardowa pochodzi od elementu UserControl i składa się z co najmniej jednej innej kontrolki.

  • Model sterowania. Kontrolka niestandardowa pochodzi z Control i służy do kompilowania implementacji, które oddzielają ich zachowanie od ich wyglądu przy użyciu szablonów, podobnie jak większość kontrolek WPF. Pochodzenie od elementu Control pozwala na większą swobodę tworzenia niestandardowego interfejsu użytkownika niż w przypadku kontrolek użytkownika, ale może wymagać większego nakładu pracy.

  • Model elementu struktury. Kontrolka niestandardowa pochodzi od elementu FrameworkElement, gdy jej wygląd jest definiowany przez niestandardową logikę renderowania (a nie szablony).

W poniższym przykładzie pokazano niestandardową kontrolkę liczbową w górę/w dół, która pochodzi z elementu UserControl:

<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.NumericUpDown">

  <Grid>

    <Grid.RowDefinitions>
      <RowDefinition/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <!-- Value text box -->
    <Border BorderThickness="1" BorderBrush="Gray" Margin="2" Grid.RowSpan="2" 
      VerticalAlignment="Center" HorizontalAlignment="Stretch">
      <TextBlock Name="valueText" Width="60" TextAlignment="Right" Padding="5"/>
    </Border>

    <!-- Up/Down buttons -->
    <RepeatButton Name="upButton" Click="upButton_Click" Grid.Column="1" 
      Grid.Row="0">Up</RepeatButton>
    <RepeatButton Name="downButton" Click="downButton_Click" Grid.Column="1" 
      Grid.Row="1">Down</RepeatButton>

  </Grid>

</UserControl>
using System; // EventArgs
using System.Windows; // DependencyObject, DependencyPropertyChangedEventArgs,
                      // FrameworkPropertyMetadata, PropertyChangedCallback,
                      // RoutedPropertyChangedEventArgs
using System.Windows.Controls; // UserControl

namespace SDKSample
{
    public partial class NumericUpDown : UserControl
    {
        // NumericUpDown user control implementation
    }
}
imports System 'EventArgs
imports System.Windows 'DependencyObject, DependencyPropertyChangedEventArgs, 
                       ' FrameworkPropertyMetadata, PropertyChangedCallback, 
                       ' RoutedPropertyChangedEventArgs
imports System.Windows.Controls 'UserControl

Namespace SDKSample

    ' Interaction logic for NumericUpDown.xaml
    Partial Public Class NumericUpDown
        Inherits System.Windows.Controls.UserControl

        'NumericUpDown user control implementation

    End Class

End Namespace

W poniższym przykładzie pokazano kod XAML wymagany do uwzględnienia kontrolki użytkownika w obiekcie Window:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.UserControlWindow"
    xmlns:local="clr-namespace:SDKSample" 
    Title="User Control Window">

  <!-- Numeric Up/Down user control -->
  <local:NumericUpDown />

</Window>

Na poniższej ilustracji przedstawiono kontrolkę NumericUpDown hostowaną w obiekcie Window:

A custom UserControl

Aby uzyskać więcej informacji na temat kontrolek niestandardowych, zobacz Omówienie tworzenia kontrolek.

Najlepsze rozwiązania dotyczące platformy WPF

Podobnie jak w przypadku dowolnej platformy programistycznej, platforma WPF może być używana na różne sposoby, aby osiągnąć pożądany wynik. Jako sposób zapewnienia, że aplikacje WPF zapewniają wymagane środowisko użytkownika i spełniają wymagania odbiorców ogólnie, istnieją zalecane najlepsze rozwiązania dotyczące ułatwień dostępu, globalizacji i lokalizacji oraz wydajności. Aby uzyskać więcej informacji, zobacz:

Następne kroki

Przyjrzeliśmy się kluczowym funkcjom WPF. Teraz nadszedł czas, aby skompilować pierwszą aplikację WPF.

Zobacz też