XAML - szybki przewodnik

XAML oznacza Extensible Application Markup Language. To prosty i deklaratywny język oparty na XML.

  • W języku XAML bardzo łatwo jest tworzyć, inicjować i ustawiać właściwości obiektu z relacjami hierarchicznymi.

  • Służy głównie do projektowania GUI.

  • Może być również używany do innych celów, np. Do deklarowania workflow w Workflow Foundation.

XAML może być używany na różnych platformach, takich jak WPF (Windows Presentation Foundation), Silverlight, Mobile Development i Windows Store App. Może być używany w różnych wersjach platformy .Net i CLR (środowisko uruchomieniowe języka wspólnego).

Jak działa XAML

XAML to plik declarative język w sensie, który definiuje WHAT i HOWchcesz robić. Procesor XAML jest odpowiedzialny zaHOWczęść, aby się dowiedzieć. Spójrzmy na następujący schemat. Podsumowuje stronę XAML -

Rysunek ilustruje następujące działania -

  • Plik XAML jest interpretowany przez procesor XAML specyficzny dla platformy.

  • Procesor XAML przekształca XAML w kod wewnętrzny, który opisuje element interfejsu użytkownika.

  • Kod wewnętrzny i kod C # są połączone ze sobą za pomocą definicji klas częściowych, a następnie kompilator .NET tworzy aplikację.

Zalety XAML

Jeden z długotrwałych problemów, z którymi wszyscy spotykamy się przy projektowaniu GUI, można rozwiązać za pomocą XAML. Może służyć do projektowania elementów interfejsu użytkownika w aplikacjach Windows Forms.

We wcześniejszych strukturach GUI nie było rzeczywistego oddzielenia między wyglądem aplikacji a zachowaniem. Zarówno GUI, jak i jego zachowanie zostały utworzone w tym samym języku, np. C # lub VB.net, co wymagałoby więcej wysiłku od programisty, aby zaimplementować zarówno interfejs użytkownika, jak i związane z nim zachowanie.

Dzięki XAML bardzo łatwo jest oddzielić zachowanie od kodu projektanta. Dlatego programista XAML i projektant mogą pracować równolegle. Kody XAML są bardzo łatwe do odczytania i zrozumienia.

Firma Microsoft udostępnia dwa ważne narzędzia dla języka XAML -

  • Visual Studio
  • Expression Blend

Obecnie oba narzędzia mogą tworzyć XAML, ale faktem jest, że Visual Studio jest częściej używany przez programistów, podczas gdy Expression Blend jest nadal częściej używany przez projektantów.

Firma Microsoft udostępnia bezpłatną wersję programu Visual Studio, którą można pobrać z witryny https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx

Note- W tym samouczku będziemy głównie używać projektów WPF i aplikacji Windows Store. Jednak bezpłatna wersja programu Visual Studio nie obsługuje aplikacji ze Sklepu Windows. W tym celu będziesz potrzebować licencjonowanej wersji programu Visual Studio.

Instalacja

Wykonaj poniższe czynności, aby zainstalować program Visual Studio w systemie -

  • Po pobraniu plików uruchom instalator. Zostanie wyświetlone następujące okno dialogowe.

  • Kliknij przycisk Instaluj, aby rozpocząć proces instalacji.

  • Po pomyślnym zakończeniu procesu instalacji zobaczysz następujący ekran.

  • Zamknij to okno dialogowe i w razie potrzeby uruchom ponownie komputer.

  • Teraz otwórz program Visual studio z menu Start, które wyświetli następujące okno dialogowe. Za pierwszym razem zajmie to trochę czasu, tylko na przygotowanie.

Po zakończeniu zobaczysz główne okno programu Visual Studio.

Pierwszy krok w kierunku wdrożenia

Zacznijmy od prostej implementacji. Wykonaj czynności podane poniżej -

  • Kliknij opcję menu Plik → Nowy → Projekt.

  • Zostanie wyświetlone następujące okno dialogowe -

  • W obszarze szablony wybierz Visual C # i wybierz aplikację WPF. Nadaj nazwę projektowi i kliknij przycisk OK.

  • W pliku mainwindow.xaml domyślnie zapisywane są następujące tagi XAML. Zrozumiesz wszystkie te tagi w dalszej części tego samouczka.

<Window x:Class = "FirstStepDemo.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:FirstStepDemo" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
         
   </Grid> 
</Window>

Domyślnie siatka jest ustawiana jako pierwszy element po stronie.

Dodajmy przycisk i blok tekstowy pod elementem Grid. To się nazywaobject element syntax, lewy nawias ostry, po którym następuje nazwa tego, co chcemy utworzyć, na przykład przycisk, a następnie zdefiniuj właściwość treści. Na przycisku zostanie wyświetlony ciąg przypisany do Treści. Teraz ustaw wysokość i szerokość przycisku odpowiednio na 30 i 50. Podobnie zainicjuj właściwości bloku tekstu.

Teraz spójrz na okno projektu. Zobaczysz przycisk. Teraz naciśnij klawisz F5, aby wykonać ten kod XAML.

<Window x:Class = "FirstStepDemo.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:FirstStepDemo" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Button Content = "First Button" Height = "30" Width = "80"/> 
      <TextBlock Text = "Congratulations you have successfully build your first app" 
         Height = "30" Margin = "162,180,122,109"/> 
   </Grid> 
	
</Window>

Podczas kompilowania i wykonywania powyższego kodu zobaczysz następujące okno.

Gratulacje! Zaprojektowałeś swój pierwszy przycisk.

Aplikacje XAML można również tworzyć na komputerach Mac. Na komputerze Mac XAML może być używany jako aplikacje dla systemów iOS i Android. Aby skonfigurować środowisko na Macu, przejdź do www.xamarin.com . Kliknij Produkty i wybierz platformę Xamarin. Pobierz Xamarin Studio i zainstaluj je. Umożliwi to tworzenie aplikacji na różne platformy.

XAML - składnia języka C #

W tym rozdziale poznasz podstawową składnię / reguły XAML do pisania aplikacji XAML. Rzućmy okiem na prosty plik XAML.

<Window x:Class = "Resources.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Grid> 
         
   </Grid> 
</Window>

Jak widać w powyższym pliku XAML, istnieją różne rodzaje tagów i elementów. Poniższa tabela pokrótce opisuje wszystkie elementy.

Sr.No Elementy i opis
1

<Window

Jest to otwierający element obiektu lub kontener katalogu głównego.

2

x:Class="Resources.MainWindow"

Jest to deklaracja klasy częściowej, która łączy znacznik z częściowym kodem klasy za zdefiniowanym w niej.

3

xmlns

Mapuje domyślną przestrzeń nazw XAML dla klienta / struktury WPF

4

xmlns:x

Przestrzeń nazw XAML dla języka XAML, który mapuje go na prefiks x:

5

>

Koniec elementu obiektu głównego.

6

<Grid>

</Grid>

Rozpoczynanie i zamykanie znaczników pustego obiektu siatki.

7

</Window>

Zamknięcie elementu obiektu

Reguły składni dla elementu obiektu

Reguły składni dla XAML są prawie podobne do XML. Jeśli spojrzysz na dokument XAML, zauważysz, że w rzeczywistości jest to prawidłowy plik XML. Jednak plik XML nie może być prawidłowym plikiem XAML. Dzieje się tak, ponieważ w języku XML wartość atrybutów musi być ciągiem, podczas gdy w języku XAML może to być inny obiekt, który jest znany jako składnia elementu właściwości.

  • Składnia elementu Object rozpoczyna się od lewego nawiasu trójkątnego (<), po którym następuje nazwa obiektu, np. Przycisk.

  • Zdefiniuj niektóre właściwości i atrybuty tego elementu obiektu.

  • Element Object musi być zamknięty ukośnikiem (/), po którym bezpośrednio następuje prawy nawias ostry (>).

Przykład prostego obiektu bez elementu podrzędnego -

<Button/>

Przykład elementu obiektu z pewnymi atrybutami -

<Button Content = "Click Me" Height = "30" Width = "60"/>

Przykład alternatywnej składni do definiowania właściwości (składnia elementu właściwości) -

<Button> 
   <Button.Content>Click Me</Button.Content> 
   <Button.Height>30</Button.Height> 
   <Button.Width>60</Button.Width> 
</Button>

Przykład obiektu z elementem podrzędnym - StackPanel zawiera Textblock jako element podrzędny

<StackPanel Orientation = "Horizontal"> 
   <TextBlock Text = "Hello"/> 
</StackPanel>

Za pomocą języka XAML można tworzyć, inicjować i ustawiać właściwości obiektów. Te same czynności można również wykonać za pomocą kodu programistycznego.

XAML to kolejny prosty i łatwy sposób projektowania elementów interfejsu użytkownika. W przypadku języka XAML to Ty decydujesz, czy chcesz zadeklarować obiekty w języku XAML, czy zadeklarować je przy użyciu kodu.

Weźmy prosty przykład, aby zademonstrować, jak pisać w języku XAML -

<Window x:Class = "XAMLVsCode.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <StackPanel> 
      <TextBlock Text = "Welcome to XAML Tutorial" Height = "20" Width = "200" Margin = "5"/>
      <Button Content = "Ok" Height = "20" Width = "60" Margin = "5"/> 
   </StackPanel> 
	
</Window>

W tym przykładzie utworzyliśmy panel stosu z blokiem przycisku i tekstu oraz zdefiniowaliśmy niektóre właściwości przycisku i bloku tekstu, takie jak wysokość, szerokość i margines. Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje następujący wynik -

Teraz spójrz na ten sam kod, który jest napisany w C #.

using System; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls;  

namespace XAMLVsCode { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window {
      public MainWindow() { 
         InitializeComponent();  
         
         // Create the StackPanel 
         StackPanel stackPanel = new StackPanel();
         this.Content = stackPanel; 
			
         // Create the TextBlock 
         TextBlock textBlock = new TextBlock(); 
         textBlock.Text = "Welcome to XAML Tutorial"; 
         textBlock.Height = 20;
         textBlock.Width = 200; 
         textBlock.Margin = new Thickness(5); 
         stackPanel.Children.Add(textBlock);  
			
         // Create the Button 
         Button button = new Button(); 
         button.Content = "OK"; 
         button.Height = 20; 
         button.Width = 50; 
         button.Margin = new Thickness(20); 
         stackPanel.Children.Add(button); 
      } 
   }
}

Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje następujący wynik. Zwróć uwagę, że jest to dokładnie to samo, co dane wyjściowe kodu XAML.

Teraz możesz zobaczyć, jak proste jest używanie i rozumienie XAML.

W tym rozdziale napiszemy ten sam przykład w VB.Net, aby osoby zaznajomione z VB.Net mogły również zrozumieć zalety XAML.

Spójrzmy ponownie na ten sam przykład, który jest napisany w języku XAML -

<Window x:Class = "XAMLVsCode.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <TextBlock Text = "Welcome to XAML Tutorial with VB.net" Height = "20" Width = "220" Margin = "5"/> 
      <Button Content = "Ok" Height = "20" Width = "60" Margin = "5"/> 
   </StackPanel> 
	
</Window>

W tym przykładzie utworzyliśmy panel stosu z przyciskiem i blokiem tekstu oraz zdefiniowaliśmy niektóre właściwości przycisku i bloku tekstu, takie jak wysokość, szerokość i margines. Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje następujący wynik -

Teraz spójrz na ten sam kod, który jest napisany w VB.Net -

Public Class MainWindow
   Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) 
      Dim panel As New StackPanel() 
      panel.Orientation = Orientation.Vertical 
      Me.Content = panel 
      Dim txtInput As New TextBlock 
		
      txtInput.Text = "Welcome to XAML Tutorial with VB.net" 
      txtInput.Width = 220 
      txtInput.Height = 20 
      txtInput.Margin = New Thickness(5) 
		
      panel.Children.Add(txtInput)  
      Dim btn As New Button()
		
      btn.Content = "Ok" 
      btn.Width = 60 
      btn.Height = 20 
      btn.Margin = New Thickness(5) 
		
      panel.Children.Add(btn)
   End Sub 
End Class

Gdy powyższy kod jest kompilowany i wykonywany, dane wyjściowe są dokładnie takie same, jak dane wyjściowe kodu XAML.

Możesz teraz wyobrazić sobie, jak prosta jest praca z XAML w porównaniu z VB.Net.

W powyższym przykładzie widzieliśmy, że to, co możemy zrobić w XAML, można również zrobić w innych językach proceduralnych, takich jak C # i VB.Net.

Rzućmy okiem na inny przykład, w którym użyjemy zarówno XAML, jak i VB.Net. Zaprojektujemy GUI w XAML, a zachowanie zostanie zaimplementowane w VB.Net.

W tym przykładzie przycisk został dodany do okna głównego. Kliknięcie tego przycisku przez użytkownika powoduje wyświetlenie komunikatu w oknie komunikatu. Oto kod w języku XAML, w którym obiekt przycisku jest zadeklarowany z niektórymi właściwościami.

<Window x:Class="MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Button Name = "btn" HorizontalAlignment = "Center" Width = "60" Height = "30" Content = "Click Me" /> 
   </Grid> 
	
</Window>

W VB.Net zaimplementowano zdarzenie (zachowanie) kliknięcia przycisku. To zdarzenie powoduje wyświetlenie wiadomości w skrzynce wiadomości.

Public Class MainWindow
   Private Sub btn_Click(sender As Object, e As RoutedEventArgs) Handles btn.Click 
      MessageBox.Show("Button is Clicked") 
   End Sub 
End Class

Kiedy powyższy kod zostanie skompilowany i wykonany, wyświetli się następujący ekran -

Teraz kliknij powyższy przycisk z napisem „Kliknij mnie”. Wyświetli następujący komunikat -

W tym rozdziale opisano niektóre podstawowe i ważne elementy składowe aplikacji XAML. Wyjaśni, jak to zrobić

  • do tworzenia i inicjalizacji obiektu,
  • obiekt można łatwo modyfikować za pomocą zasobów, stylów i szablonów,
  • uczynić obiekt interaktywnym za pomocą przekształceń i animacji.

Obiekty

XAML to typowo deklaratywny język, który może tworzyć i tworzyć wystąpienia obiektów. To kolejny sposób na opisanie obiektów opartych na XML, czyli o tym, które obiekty trzeba stworzyć i jak powinny zostać zainicjowane przed wykonaniem programu. Obiekty mogą być

  • Pojemniki (panel stosu, panel dokujący)
  • Elementy / elementy interfejsu użytkownika (przycisk, pole tekstowe itp.)
  • Słowniki zasobów

Zasoby

Zasoby są zwykle definicjami związanymi z jakimś przedmiotem, którego po prostu spodziewasz się używać częściej niż raz. Jest to możliwość lokalnego przechowywania danych dla kontrolek lub dla bieżącego okna lub globalnie dla całych aplikacji.

Style

Struktura XAML udostępnia kilka strategii personalizowania i dostosowywania wyglądu aplikacji. Style zapewniają nam elastyczność w ustawianiu niektórych właściwości obiektu i ponownym użyciu tych określonych ustawień w wielu obiektach w celu uzyskania spójnego wyglądu.

  • W stylach możesz ustawić tylko istniejące właściwości obiektu, takie jak wysokość, szerokość, rozmiar czcionki itp.
  • Można określić tylko domyślne zachowanie formantu.
  • Do stylu można dodać wiele właściwości.

Na pierwszym diagramie widać, że te same właściwości wysokości i szerokości są ustawione oddzielnie dla wszystkich trzech przycisków; ale na drugim diagramie widać, że wysokość i szerokość, które są takie same dla wszystkich przycisków, są dodawane do stylu, a następnie ten styl jest powiązany ze wszystkimi przyciskami.

Szablony

Szablon opisuje ogólny wygląd i wygląd kontrolki. Z każdą kontrolką jest skojarzony domyślny szablon, który nadaje wygląd tej kontrolce. W języku XAML możesz łatwo tworzyć własne szablony, gdy chcesz dostosować zachowanie wizualne i wygląd kontrolki.

Na poniższym zrzucie ekranu znajdują się dwa przyciski, jeden z szablonem, a drugi to przycisk domyślny.

Teraz po najechaniu myszą na przycisk zmienia on również kolor, jak pokazano poniżej.

Dzięki szablonom możesz uzyskać dostęp do większej liczby części kontrolki niż w stylach. Można określić istniejące i nowe zachowanie formantu.

Animacje i transformacje

Animacje i transformacje w środowisku wykonawczym systemu Windows mogą ulepszyć aplikację XAML, budując interaktywność i ruch. Możesz łatwo zintegrować interaktywny wygląd i zachowanie w aplikacji XAML, używając animacji z biblioteki animacji środowiska wykonawczego systemu Windows. Używane są animacje

  • aby ulepszyć interfejs użytkownika lub uczynić go bardziej atrakcyjnym.
  • aby zwrócić uwagę użytkownika na zmianę.

Na poniższym zrzucie ekranu widać kwadrat -

Kiedy najedziesz kursorem myszy na ten kwadrat, rozwinie się on we wszystkich kierunkach, jak pokazano poniżej.

Struktura interfejsu użytkownika XAML oferuje obszerną bibliotekę formantów obsługujących tworzenie interfejsu użytkownika dla systemu Windows. Niektóre z nich mają wizualną reprezentację, taką jak Button, Textbox, TextBlock itp .; podczas gdy inne kontrolki są używane jako kontenery dla innych kontrolek lub zawartości, na przykład obrazów. Wszystkie kontrolki XAML są dziedziczone zSystem.Windows.Controls.Control.

Pełna hierarchia dziedziczenia formantów jest następująca -

Oto lista kontrolek, które omówimy po kolei w tym rozdziale.

Sr.No. Sterowanie i opis
1 Przycisk

Kontrolka, która reaguje na dane wejściowe użytkownika.

2 Kalendarz

Reprezentuje kontrolkę, która umożliwia użytkownikowi wybranie daty przy użyciu wyświetlania kalendarza wizualnego.

3 CheckBox

Kontrolka, którą użytkownik może wybrać lub wyczyścić.

4 ComboBox

Rozwijana lista elementów, z których użytkownik może wybierać.

5 Menu kontekstowe

Pobiera lub ustawia element menu kontekstowego, który powinien być wyświetlany za każdym razem, gdy menu kontekstowe jest żądane za pośrednictwem interfejsu użytkownika (UI) z poziomu tego elementu.

6 Siatka danych

Reprezentuje kontrolkę wyświetlającą dane w dostosowywalnej siatce.

7 DatePicker

Kontrolka, która pozwala użytkownikowi wybrać datę.

8 Dialogi

Aplikacja może również wyświetlać użytkownikowi dodatkowe okna w celu zebrania lub wyświetlenia ważnych informacji.

9 GridView

Kontrolka przedstawiająca kolekcję elementów w wierszach i kolumnach, które można przewijać w poziomie.

10 Wizerunek

Kontrolka przedstawiająca obraz.

11 Skrzynka na listy

Kontrolka przedstawiająca wbudowaną listę elementów, z których użytkownik może wybierać.

12 Menu

Reprezentuje kontrolkę menu systemu Windows, która umożliwia hierarchiczne organizowanie elementów skojarzonych z poleceniami i programami obsługi zdarzeń.

13 PasswordBox

Formant do wprowadzania haseł.

14 Popup

Wyświetla zawartość nad istniejącą zawartością, w granicach okna aplikacji.

15 Pasek postępu

Kontrolka wskazująca postęp poprzez wyświetlenie paska.

16 ProgressRing

Kontrolka, która wskazuje nieokreślony postęp, wyświetlając pierścień.

17 Przycisk radiowy

Kontrolka, która umożliwia użytkownikowi wybranie pojedynczej opcji z grupy opcji.

18 RichEditBox

Kontrolka, która umożliwia użytkownikowi edytowanie dokumentów z tekstem sformatowanym z zawartością, taką jak tekst sformatowany, hiperłącza i obrazy.

19 ScrollViewer

Formant kontenera, który umożliwia użytkownikowi przesuwanie i powiększanie jego zawartości.

20 SearchBox

Kontrolka, która umożliwia użytkownikowi wprowadzanie zapytań wyszukiwania.

21 Suwak

Kontrolka, która umożliwia użytkownikowi wybieranie z zakresu wartości przez przesuwanie kontrolki Thumb wzdłuż ścieżki.

22 TextBlock

Kontrolka wyświetlająca tekst.

23 TimePicker

Kontrolka, która umożliwia użytkownikowi ustawienie wartości czasu.

24 ToggleButton

Przycisk, który można przełączać między 2 stanami.

25 ToolTip

Wyskakujące okienko, które wyświetla informacje o elemencie.

26 Okno

Okno główne, które zapewnia opcję minimalizacji / maksymalizacji, pasek tytułu, ramkę i przycisk zamykania.

W tym rozdziale omówimy wszystkie te kontrole wraz z wdrażaniem.

Układ elementów sterujących jest bardzo ważny i krytyczny dla użyteczności aplikacji. Wymagane jest zaaranżowanie w aplikacji grupy elementów GUI. Przy wyborze paneli układu należy wziąć pod uwagę kilka ważnych kwestii;

  • Pozycje elementów potomnych.
  • Rozmiary elementów podrzędnych.
  • Nakładanie nakładających się elementów potomnych jeden na drugi.

Stały układ pikseli elementów sterujących nie działa, gdy aplikacja była używana na różnych rozdzielczościach ekranu. XAML zapewnia bogaty zestaw wbudowanych paneli układu do odpowiedniego rozmieszczania elementów GUI. Oto niektóre z najczęściej używanych i popularnych paneli układu -

Sr.No Panele i opis
1 StackPanel

Panel stosu to prosty i przydatny panel układu w języku XAML. W panelu stosu elementy podrzędne można układać w jednym wierszu, poziomo lub pionowo, w zależności od właściwości orientacji.

2 WrapPanel

W WrapPanel elementy podrzędne są umieszczane w kolejności od lewej do prawej lub od góry do dołu na podstawie właściwości orientacji.

3 DockPanel

DockPanel definiuje obszar do rozmieszczenia elementów podrzędnych względem siebie w poziomie lub w pionie. Dzięki DockPanel możesz łatwo zadokować elementy podrzędne na górze, na dole, w prawo, w lewo iw środku za pomocą właściwości Dock.

4 CanvasPanel

Panel Canvas to podstawowy panel układu, w którym elementy podrzędne można ustawić jawnie za pomocą współrzędnych odnoszących się do obszaru Canvas po dowolnej stronie, takiej jak lewa, prawa, góra i dół.

5 GridPanel

Panel Siatka zapewnia elastyczny obszar składający się z wierszy i kolumn. W siatce elementy podrzędne można układać w formie tabelarycznej.

Ogólna koncepcja zdarzeń w XAML jest podobna do zdarzeń w innych popularnych językach programowania, takich jak .NET i C ++. W języku XAML wszystkie kontrolki uwidaczniają niektóre zdarzenia, aby można je było subskrybować do określonych celów.

Za każdym razem, gdy ma miejsce zdarzenie, aplikacja zostanie o tym powiadomiona, a program będzie mógł na nie zareagować, np. Do zamknięcia okna służą przyciski zamykania.

Istnieje wiele typów zdarzeń, które można subskrybować dla różnych zachowań aplikacji w oparciu o wymagania tej aplikacji, ale najczęściej używane są zdarzenia związane z myszą i klawiaturą, np.

  • Click
  • MouseDown
  • MouseEnter
  • MouseLeave
  • MouseUp
  • KeyDown
  • KeyUp

W tym rozdziale wykorzystamy niektóre z podstawowych i najczęściej używanych zdarzeń, aby zrozumieć, w jaki sposób zdarzenie określonej kontrolki może być połączone z kodem, za którym zostanie zaimplementowane zachowanie w zależności od tego, co użytkownik chce zrobić, gdy określone zdarzenie występuje.

Przyjrzyjmy się prostemu przykładowi zdarzenia kliknięcia przycisku. Poniżej podano implementację XAML dla formantu Button, który jest tworzony i inicjowany z niektórymi właściwościami i zdarzeniem Click (Click = "OnClick").

<Window x:Class = "XAMLEventHandling.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Button x:Name = "button1" Content = "Click" Click = "OnClick" 
         Width = "150" Height = "30" HorizontalAlignment = "Center" /> 
   </Grid>
   
</Window>

Każde kliknięcie tego przycisku spowoduje uruchomienie pliku OnClickzdarzenie i możesz dodać dowolny typ zachowania jako odpowiedź na kliknięcie. Przyjrzyjmy się implementacji zdarzenia OnClick, która wyświetli komunikat po kliknięciu tego przycisku.

using System; 
using System.Windows; 
using System.Windows.Controls;  

namespace XAMLEventHandling {
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window {
      public MainWindow() { 
         InitializeComponent(); 
      }
      private void OnClick(object sender, RoutedEventArgs e) { 
         MessageBox.Show("Button is clicked!"); 
      } 
   }
}

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik -

Po kliknięciu przycisku zostanie uruchomione zdarzenie click (OnClick) i zostanie wyświetlony następujący komunikat.

Teraz przyjrzyjmy się nieco złożonemu przykładowi, w którym obsługiwanych jest wiele zdarzeń.

Przykład

Poniższy przykład zawiera pole tekstowe z ContextMenu, które manipuluje tekstem w polu tekstowym.

Poniższy kod XAML tworzy TextBox, ContextMenu i MenuItems z niektórymi właściwościami i zdarzeniami, takimi jak Checked, Unchecked i Click.

<Window x:Class = "XAMLContextMenu.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <TextBox Name = "textBox1" TextWrapping = "Wrap" Margin = "10" Grid.Row = "7"> 
         Hi, this is XAML tutorial. 
         <TextBox.ContextMenu>
         
            <ContextMenu>
               <MenuItem Header = "_Bold" IsCheckable = "True" 
                  Checked = "Bold_Checked" Unchecked = "Bold_Unchecked" /> 
               <MenuItem Header = "_Italic" IsCheckable = "True" 
                  Checked = "Italic_Checked" Unchecked = "Italic_Unchecked" /> 
               <Separator /> 
               <MenuItem Header = "Increase Font Size" Click = "IncreaseFont_Click" />
               <MenuItem Header = "_Decrease Font Size" Click = "DecreaseFont_Click" /> 
            </ContextMenu> 
				
         </TextBox.ContextMenu>
      </TextBox>
   </Grid> 
	
</Window>

Oto implementacja w języku C # dla różnych zdarzeń, które będą uruchamiane za każdym razem, gdy element menu zostanie zaznaczony, odznaczony lub kliknięty.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data;  

namespace XAMLContextMenu { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary>
	
   public partial class MainWindow : Window {
      public MainWindow() { 
         InitializeComponent(); 
      }
      private void Bold_Checked(object sender, RoutedEventArgs e) { 
         textBox1.FontWeight = FontWeights.Bold; 
      }
      private void Bold_Unchecked(object sender, RoutedEventArgs e) { 
         textBox1.FontWeight = FontWeights.Normal; 
      }
      private void Italic_Checked(object sender, RoutedEventArgs e) { 
         textBox1.FontStyle = FontStyles.Italic; 
      }
      private void Italic_Unchecked(object sender, RoutedEventArgs e) { 
         textBox1.FontStyle = FontStyles.Normal; 
      }
      private void IncreaseFont_Click(object sender, RoutedEventArgs e) { 
         if (textBox1.FontSize < 18) { 
            textBox1.FontSize += 2; 
         } 
      }
      private void DecreaseFont_Click(object sender, RoutedEventArgs e) { 
         if (textBox1.FontSize > 10) { 
            textBox1.FontSize -= 2; 
         } 
      }
   }
}

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik -

Zalecamy wykonanie powyższego przykładowego kodu i eksperymentowanie z innymi zdarzeniami.

Wydarzenia

Sr.No. Sterowanie i opis
1

Checked

Uruchamiany po zaznaczeniu ToggleButton. (Odziedziczone po ToggleButton)

2

Click

Występuje po kliknięciu kontrolki przycisku. (Odziedziczone po ButtonBase)

3

ContextMenuClosing

Występuje tuż przed zamknięciem dowolnego menu kontekstowego elementu. (Odziedziczone po FrameworkElement).

4

ContextMenuOpening

Występuje po otwarciu dowolnego menu kontekstowego elementu. (Odziedziczone po FrameworkElement).

5

DataContextChanged

Występuje po zmianie wartości właściwości FrameworkElement.DataContext. (Odziedziczone po FrameworkElement)

6

DragEnter

Występuje, gdy system wejściowy zgłasza bazowe zdarzenie przeciągania z tym elementem jako celem. (Odziedziczone po UIElement).

7

DragLeave

Występuje, gdy system wejściowy zgłasza bazowe zdarzenie przeciągania z tym elementem jako źródłem. (Odziedziczone po UIElement)

8

DragOver

Występuje, gdy system wejściowy zgłasza bazowe zdarzenie przeciągania z tym elementem jako potencjalnym celem upuszczania. (Odziedziczone po UIElement)

9

DragStarting

Występuje po zainicjowaniu operacji przeciągania. (Odziedziczone po UIElement)

10

DropCompleted

Występuje po zakończeniu operacji przeciągania i upuszczania. (Odziedziczone po UIElement)

11

DropDownClosed

Występuje po zamknięciu rozwijanej części ComboBox.

12

DropDownOpened

Występuje, gdy zostanie otwarta rozwijana część ComboBox.

13

GotFocus

Występuje, gdy UIElement otrzyma fokus. (Odziedziczone po UIElement)

14

Holding

Występuje, gdy w innym przypadku nieobsłużona interakcja Hold w obszarze testu trafień tego elementu. (Odziedziczone po UIElement)

15

Intermediate

Pożary, gdy stan ToggleButton zostanie przełączony na stan nieokreślony. (Odziedziczone po ToggleButton)

16

IsEnabledChanged

Występuje po zmianie właściwości IsEnabled. (Odziedziczone po Control)

17

KeyDown

Występuje po naciśnięciu klawisza klawiatury, gdy element UIElement ma fokus. (Odziedziczone po UIElement)

18

KeyUp

Występuje po wydaniu klawisza klawiatury, gdy element UIElement ma fokus. (Odziedziczone po UIElement)

19

LostFocus

Występuje, gdy element UIElement traci fokus. (Odziedziczone po UIElement)

20

ManipulationCompleted

Występuje po zakończeniu manipulacji na UIElement. (Odziedziczone po UIElement)

21

ManipulationDelta

Występuje, gdy urządzenie wejściowe zmienia położenie podczas manipulacji. (Odziedziczone po UIElement)

22

ManipulationInertiaStarting

Występuje, gdy urządzenie wejściowe traci kontakt z obiektem UIElement podczas manipulacji i rozpoczyna się bezwładność. (Odziedziczone po UIElement)

23

ManipulationStarted

Występuje, gdy urządzenie wejściowe rozpoczyna manipulację na UIElement. (Odziedziczone po UIElement)

24

ManipulationStarting

Występuje po pierwszym utworzeniu procesora manipulacji. (Odziedziczone po UIElement)

25

SelectionChanged

Występuje po zmianie zaznaczenia tekstu.

26

SizeChanged

Występuje, gdy właściwość ActualHeight lub ActualWidth zmieni wartość na FrameworkElement. (Odziedziczone po FrameworkElement)

27

Unchecked

Występuje, gdy ToggleButton nie jest zaznaczone. (Odziedziczone po ToggleButton)

28

ValueChanged

Występuje po zmianie wartości zakresu. (Odziedziczone po RangeBase)

Powiązanie danych to mechanizm w aplikacjach XAML, który zapewnia prosty i łatwy sposób dla aplikacji środowiska wykonawczego systemu Windows przy użyciu klas częściowych do wyświetlania danych i interakcji z nimi. Zarządzanie danymi jest całkowicie oddzielone od sposobu wyświetlania danych w tym mechanizmie.

Powiązanie danych umożliwia przepływ danych między elementami interfejsu użytkownika a obiektem danych w interfejsie użytkownika. Po ustanowieniu powiązania i zmianie danych lub modelu biznesowego aktualizacje zostaną automatycznie odzwierciedlone w elementach interfejsu użytkownika i odwrotnie. Możliwe jest również powiązanie nie ze standardowym źródłem danych, ale raczej z innym elementem na stronie. Powiązanie danych może być dwojakiego rodzaju -

  • Jednokierunkowe wiązanie danych
  • Dwukierunkowe wiązanie danych

Jednokierunkowe wiązanie danych

W powiązaniu jednokierunkowym dane są wiązane ze źródła (czyli obiektu, który je przechowuje) do celu (czyli obiektu, który wyświetla dane).

Rzućmy okiem na prosty przykład jednokierunkowego wiązania danych. Poniższy kod XAML tworzy cztery bloki tekstowe z niektórymi właściwościami.

<Window x:Class = "DataBindingOneWay.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid>
      <StackPanel Name = "Display">
         <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0"> 
            <TextBlock Text = "Name: " Margin = "10" Width = "100" /> 
            <TextBlock Margin = "10" Width = "100" Text = "{Binding Name}" />
         </StackPanel> 
		
         <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0"> 
            <TextBlock Text = "Title: " Margin = "10" Width = "100" /> 
            <TextBlock Margin = "10" Width = "100" Text = "{Binding Title}" /> 
         </StackPanel>
      </StackPanel>
   </Grid> 
	
</Window>

Właściwości tekstowe dwóch bloków tekstowych są ustawiane statycznie na „Nazwisko” i „Tytuł”, podczas gdy pozostałe dwa bloki tekstowe Właściwości tekstu są powiązane z „Nazwą” i „Tytułem”, które są zmiennymi klasowymi klasy Pracownik, co pokazano poniżej.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
 
namespace DataBindingOneWay {
   public class Employee {
      public string Name { get; set; } 
      public string Title { get; set; }  
		
      public static Employee GetEmployee() {
         var emp = new Employee() { 
            Name = "Ali Ahmed", Title = "Developer" 
         }; 
         return emp; 
      }
   }
}

W tej klasie mamy tylko dwie zmienne, Name i Titlei jedną statyczną metodę, w której obiekt Employee jest inicjowany, co zwróci ten obiekt pracownika. Więc jesteśmy związani z właściwością, nazwą i tytułem, ale nie wybraliśmy, do jakiego obiektu należy ta właściwość. Najłatwiejszym sposobem jest przypisanie obiektu do DataContext, którego właściwości łączymy w poniższym kodzie C # -

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace DataBindingOneWay { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window {
      public MainWindow() { 
         InitializeComponent(); 
         DataContext = Employee.GetEmployee(); 
      } 
   }
}

Uruchommy tę aplikację i od razu zobaczysz w naszym MainWindow, że pomyślnie powiązaliśmy z nazwą i tytułem tego obiektu pracownika.

Dwukierunkowe wiązanie danych

In two-way binding, the user can modify the data through the user interface and have that data updated in the source. If the source changes while the user is looking at the view, you would want to update the view.

Example

Let’s have a look at the following example in which one combobox with three combobox items and one textbox are created with some properties. In this example, we don’t have any standard data source, but the UI elements are bound to other UI elements.

<Window x:Class = "XAMLTestBinding.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel>
      <ComboBox Name = "comboBox"  Margin = "50" Width = "100"> 
         <ComboBoxItem Content = "Green" /> 
         <ComboBoxItem Content = "Yellow" IsSelected = "True" /> 
         <ComboBoxItem Content = "Orange" /> 
      </ComboBox>
		
      <TextBox  Name = "textBox" Margin = "50" 
         Width = "100" Height = "23" VerticalAlignment = "Top" 
         Text  = "{Binding ElementName = comboBox, Path = SelectedItem.Content, 
         Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" 
         Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}"> 
      </TextBox>
   </StackPanel> 
	
</Window>

When you compile and execute the above code, it will produce the following output. When the user selects an item from the combobox, the textbox text and the background color will be updated accordingly.

Similarly, when the user types a valid color name in the textbox, then the combobox and the textbox background color will also be updated.

In XAML applications, markup extensions are a method/technique to gain a value that is neither a specific XAML object nor a primitive type. Markup extensions can be defined by opening and closing curly braces and inside that curly braces, the scope of the markup extension is defined.

Data binding and static resources are markup extensions. There are some predefined XAML markup extensions in System.xaml which can be used.

Let’s have a look at a simple example where StaticResources markup extension is used which is a predefined XAML markup extension.

The following XAML code creates two text blocks with some properties and their foreground is defined in Window.Resources.

<Window x:Class = "XAMLStaticResourcesMarkupExtension.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Window.Resources> 
      <SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush> 
   </Window.Resources> 
	
   <Grid> 
      <StackPanel Orientation = "Vertical"> 
         <TextBlock Foreground = "{StaticResource myBrush}" Text = "First Name" 
            Width = "100" Margin = "10" /> 
         <TextBlock Foreground = "{StaticResource myBrush}" Text = "Last Name" 
            Width = "100" Margin = "10" /> 
      </StackPanel> 
   </Grid> 
	
</Window>

In Window.Resources, you can see x:Key is used which uniquely identifies the elements that are created and referenced in an XAML defined dictionary to identify a resource in a resource dictionary.

When you compile and execute the above code, it will produce the following MainWindow. You can see the two text blocks with blue foreground color.

In XAML, custom markup extensions can also be defined by inheriting MarkupExtension class and overriding the ProvideValue method which is an abstract method in the MarkupExtension class.

Let’s have a look at a simple example of custom markup extension.

<Window x:Class = "XAMLMarkupExtension.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:my = "clr-namespace:XAMLMarkupExtension" 
   Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Grid> 
      <Button Content = "{my:MyMarkupExtension FirstStr = Markup, SecondStr = Extension}" 
         Width = "200" Height = "20" /> 
   </Grid> 
	
</Window>

In the above XAML code, a button is created with some properties and for the content value, a custom markup extension (my:MyMarkupExtension) has been used with two values “Markup” and “Extension” which are assigned to FirstStr and SecondStr respectively.

Actually, MyMarkupExtension is a class which is derived from MarkupExtension as shown below in the C# implementation. This class contains two string variables, FirstStr and SecondStr, which are concatenated and return that string from the ProvideValue method to the Content of a button.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;
 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Markup; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes;  

namespace XAMLMarkupExtension { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window { 
      public MainWindow() { 
         InitializeComponent(); 
      } 
   }
   public class MyMarkupExtension : MarkupExtension { 
      public MyMarkupExtension() { } 
      public String FirstStr { get; set; } 
      public String SecondStr { get; set; }  
		
      public override object ProvideValue(IServiceProvider serviceProvider) { 
        return FirstStr + " " + SecondStr; 
      } 
   }
}

Let's run this application and you can see immediately in our MainWindow that "markup extension" has been successfully used as the content of the button.

A dependency property is a specific type of property where the value is followed by a keen property system which is also a part of the Windows Runtime App. A class which defines a dependency property must be inherited from the DependencyObject class.

Many of the UI control classes which are used in XAML are derived from the DependencyObject class and support dependency properties. The following XAML code creates a button with some properties.

<Window x:Class = "XAMLDependencyProperty.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:XAMLDependencyProperty"
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid>
      <Button Height = "40" Width = "175" Margin = "10" Content = "Dependency Property">
         <Button.Style>
            <Style TargetType = "{x:Type Button}">
               <Style.Triggers> 
                  <Trigger Property = "IsMouseOver" Value = "True">
                     <Setter Property = "Foreground" Value = "Red" />
                  </Trigger>
               </Style.Triggers>
            </Style>
         </Button.Style>
      </Button>
   </Grid>
   
</Window>

Rozszerzenie znacznika x: Type w XAML ma podobną funkcjonalność, jak typeof () w C #. Jest używany, gdy określono atrybuty przyjmujące typ obiektu, na przykład <Style TargetType = "{x: Type Button}">

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący plik MainWindow. Kiedy mysz znajduje się nad przyciskiem, zmienia kolor pierwszego planu przycisku. Kiedy mysz opuści przycisk, powróci do swojego pierwotnego koloru.

Główną różnicą między właściwościami zależności a innymi właściwościami środowiska CLR są -

  • Właściwości CLR mogą bezpośrednio odczytywać / zapisywać z prywatnego elementu członkowskiego klasy przy użyciu getter i setter. W przypadku właściwości zależności nie jest przechowywany w obiekcie lokalnym.

  • Właściwości zależności są przechowywane w słowniku par klucz / wartość, który jest udostępniany przez klasę DependencyObject.

  • Oszczędza również dużo pamięci, ponieważ przechowuje właściwość po zmianie.

  • Może być również powiązany w języku XAML.

W środowisku .NET można również zdefiniować niestandardowe właściwości zależności. Oto kroki, aby zdefiniować niestandardową właściwość zależności w C #.

  • Zadeklaruj i zarejestruj swoją właściwość zależności w rejestrze wywołań systemowych.

  • Podaj metodę ustawiającą i pobierającą dla właściwości.

  • Zdefiniuj procedurę obsługi statycznej, aby obsłużyć wszelkie zmiany zachodzące globalnie.

  • Zdefiniuj procedurę obsługi instancji, aby obsłużyć wszelkie zmiany zachodzące w tej konkretnej instancji.

Poniżej podano kod w języku C # dla właściwości zależności, która została zdefiniowana w celu ustawienia właściwości SetText kontrolki użytkownika.

using System; 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication3 {
   /// <summary> 
      /// Interaction logic for UserControl1.xaml 
   /// </summary> 
	
   public partial class UserControl1 : UserControl {
      public UserControl1() {
         InitializeComponent();
      }
      public static readonly DependencyProperty
         SetTextProperty = DependencyProperty.Register("SetText", typeof(string), 
         typeof(UserControl1), new PropertyMetadata("", 
         new PropertyChangedCallback(OnSetTextChanged)));
      public string SetText {
         get {return(string) GetValue(SetTextProperty); }
         set {SetValue(SetTextProperty, value);}
      }
      private static void OnSetTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
         UserControl1 UserControl1Control = d as UserControl1;
         UserControl1Control.OnSetTextChanged(e);
      }
      private void OnSetTextChanged(DependencyPropertyChangedEventArgs e) {
         tbTest.Text = e.NewValue.ToString();
      }
   }
}

Oto plik XAML, w którym TextBlock jest zdefiniowany jako kontrolka użytkownika, a właściwość Text zostanie do niego przypisana przez właściwość zależności SetText.

Poniższy kod XAML tworzy kontrolkę użytkownika z zainicjowaniem jej właściwości zależności SetText i niektórych innych właściwości.

<Window x:Class = "WpfApplication3.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:views = "clr-namespace:WpfApplication3" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid>
      <views:UserControl1 SetText = "Hellow World" />
   </Grid>
	
</Window>

Uruchommy tę aplikację i od razu zobaczysz w naszym MainWindow, że właściwość zależności dla kontroli użytkownika została pomyślnie użyta jako Text.

Zasoby są zwykle definicjami związanymi z jakimś przedmiotem, którego po prostu spodziewasz się używać częściej niż raz. Ma możliwość lokalnego przechowywania danych dla kontrolek lub dla bieżącego okna lub globalnie dla całych aplikacji.

Zdefiniowanie obiektu jako zasobu umożliwia nam dostęp do niego z innego miejsca. W związku z tym umożliwia wielokrotne użycie. Zasoby są definiowane w słownikach zasobów, a każdy obiekt można zdefiniować jako zasób, dzięki czemu jest on zasobem, który można udostępniać. Unikatowy klucz jest określony dla zasobu XAML i przy użyciu tego klucza można odwoływać się do niego przy użyciu rozszerzenia znaczników StaticResource.

Spójrzmy jeszcze raz na prosty przykład, w którym dwa bloki tekstu są tworzone z pewnymi właściwościami, a ich kolor pierwszego planu jest zdefiniowany w programie Window.Resources.

<Window x:Class = "XAMLResources.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Window.Resources> 
      <SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush> 
   </Window.Resources>  
	
   <StackPanel Orientation = "Vertical"> 
      <TextBlock Foreground = "{StaticResource myBrush}" 
         Text = "First Name" Width = "100" Margin = "10" /> 
      <TextBlock Foreground = "{StaticResource myBrush}" 
         Text = "Last Name" Width = "100" Margin = "10" /> 
   </StackPanel> 
	
</Window>

Gdy powyższy kod zostanie skompilowany i wykonany, utworzy następujące MainWindow. Możesz zobaczyć dwa bloki tekstu z niebieskim kolorem pierwszego planu. Zaletą zasobu jest to, że jeśli istnieje wiele bloków tekstu i chcesz zmienić ich kolor tła, wystarczy zmienić go w słowniku zasobów.

Zakres zasobów

Zasoby są definiowane w słownikach zasobów, ale istnieje wiele miejsc, w których można zdefiniować słownik zasobów. W powyższym przykładzie słownik zasobów jest zdefiniowany na poziomie okna / strony. W jakim słowniku zasób jest zdefiniowany, natychmiast ogranicza zakres tego zasobu. Zatem zakres, tj. Gdzie możesz użyć zasobu, zależy od tego, gdzie go zdefiniowałeś.

  • Zdefiniuj zasób w słowniku zasobów siatki i jest dostępny tylko dla tej siatki i jej elementów podrzędnych.

  • Zdefiniuj go w oknie / na stronie i jest dostępny dla wszystkich elementów tego okna / strony.

  • Katalog główny aplikacji można znaleźć w słowniku zasobów App.xaml. Jest to katalog główny naszej aplikacji, więc zdefiniowane tutaj zasoby obejmują całą aplikację.

Jeśli chodzi o zakres zasobu, najczęściej są to poziom aplikacji, poziom strony i określony poziom elementu, taki jak Grid, StackPanel itp.

Słowniki zasobów

Słowniki zasobów w aplikacjach XAML implikują słowniki zasobów w oddzielnych plikach. Jest śledzony w prawie wszystkich aplikacjach XAML. Definiowanie zasobów w oddzielnych plikach może mieć następujące zalety -

  • Separacja między definiowaniem zasobów w słowniku zasobów a kodem związanym z interfejsem użytkownika.

  • Zdefiniowanie wszystkich zasobów w oddzielnym pliku, takim jak App.xaml, spowodowałoby udostępnienie ich w całej aplikacji.

Jak więc możemy zdefiniować nasze zasoby w słowniku zasobów w oddzielnym pliku? Cóż, jest to bardzo łatwe, wystarczy dodać nowy słownik zasobów za pośrednictwem programu Visual Studio, wykonując następujące czynności -

  • W swoim rozwiązaniu dodaj nowy folder i nadaj mu nazwę ResourceDictionaries.

  • Kliknij prawym przyciskiem myszy ten folder i wybierz opcję Słownik zasobów z pozycji Dodaj podmenu i nadaj mu nazwę DictionaryWithBrush.xaml

Przyjrzyjmy się tej samej aplikacji; tylko słownik zasobów jest teraz zdefiniowany na poziomie aplikacji.

Oto kod XAML dla pliku MainWindow.xaml.

<Window x:Class = "XAMLResources.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel Orientation = "Vertical"> 
      <TextBlock Foreground = "{StaticResource myBrush}" Text = "First Name" 
         Width = "100" Margin = "10" /> 
      <TextBlock Foreground = "{StaticResource myBrush}" Text = "Last Name" 
         Width = "100" Margin = "10"/> 
   </StackPanel> 
	
</Window>

Oto implementacja w DictionaryWithBrush.xaml -

<ResourceDictionary 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"> 
	
   <SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush> 
	
</ResourceDictionary>

Oto implementacja w app.xaml -

<Application x:Class = "XAMLResources.App" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   StartupUri = "MainWindow.xaml"> 
	
   <Application.Resources> 
      <ResourceDictionary Source = " XAMLResources\ResourceDictionaries\DictionaryWithBrush.xaml" /> 
   </Application.Resources> 
	
</Application>

Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje następujący wynik -

Zalecamy wykonanie powyższego kodu i eksperymentowanie z większą ilością zasobów, takich jak kolor tła itp.

Szablon opisuje ogólny wygląd i wygląd kontrolki. Z każdą kontrolką jest skojarzony domyślny szablon, który nadaje wygląd tej kontrolce.

W języku XAML możesz łatwo tworzyć własne szablony, gdy chcesz dostosować zachowanie wizualne i wygląd kontrolki. Łączność między logiką a szablonem można osiągnąć za pomocą powiązania danych.

Główną różnicą między stylami a szablonami są -

  • Style mogą zmieniać wygląd kontrolki tylko przy użyciu domyślnych właściwości tej kontrolki.

  • Dzięki szablonom możesz uzyskać dostęp do większej liczby części kontrolki niż w stylach. Możesz również określić istniejące i nowe zachowanie formantu.

Istnieją dwa typy szablonów, które są najczęściej używane.

  • Szablon kontroli
  • Szablon danych

Szablon kontroli

Szablon kontroli definiuje lub określa wygląd i strukturę kontrolki. Wszystkie elementy interfejsu użytkownika mają pewien rodzaj wyglądu i zachowania, np. Button ma wygląd i zachowanie. Zdarzenie kliknięcia lub najechania myszą to zachowania wywoływane w odpowiedzi na kliknięcie i najechanie myszą, a także domyślny wygląd przycisku, który można zmienić za pomocą szablonu sterowania.

Spójrzmy ponownie na prosty przykład, w którym utworzono dwa przyciski z pewnymi właściwościami. Jeden jest ztemplate a drugi jest z default przycisk.

<Window x:Class = "TemplateDemo.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Window.Resources>
      <ControlTemplate x:Key = "ButtonTemplate" TargetType = "Button">
         <Grid>
            <Ellipse x:Name = "ButtonEllipse" Height = "100" Width = "150" >
               <Ellipse.Fill> 
                  <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4"> 
                     <GradientStop Offset = "0" Color = "Red"/>
                     <GradientStop Offset = "1" Color = "Orange"/>
                  </LinearGradientBrush> 
               </Ellipse.Fill>
            </Ellipse>
            <ContentPresenter Content = "{TemplateBinding Content}"
               HorizontalAlignment = "Center" VerticalAlignment = "Center" />
         </Grid>
         <ControlTemplate.Triggers> 
            <Trigger Property = "IsMouseOver" Value = "True">
               <Setter TargetName = "ButtonEllipse" Property = "Fill" >
                  <Setter.Value> 
                     <LinearGradientBrush StartPoint = "0,0.2" EndPoint="0.2,1.4"> 
                        <GradientStop Offset = "0" Color = "YellowGreen"/>
                        <GradientStop Offset = "1" Color = "Gold"/>
                     </LinearGradientBrush> 
                  </Setter.Value> 
               </Setter>
            </Trigger> 
				
            <Trigger Property = "IsPressed" Value = "True"> 
               <Setter Property = "RenderTransform"> 
                  <Setter.Value> 
                     <ScaleTransform ScaleX = "0.8" ScaleY = "0.8" CenterX = "0" CenterY = "0" /> 
                  </Setter.Value> 
               </Setter> 
					
               <Setter Property = "RenderTransformOrigin" Value = "0.5,0.5" /> 
            </Trigger>
         </ControlTemplate.Triggers>
      </ControlTemplate> 
   </Window.Resources>
	
   <StackPanel> 
      <Button Content = "Round Button!" Template = "{StaticResource ButtonTemplate}" 
         Width = "150" Margin = "50" />
      <Button Content = "Default Button!" Height = "40" Width = "150" Margin = "5" /> 
   </StackPanel> 
	
</Window>

Kiedy powyższy kod zostanie skompilowany i wykonany, wygeneruje następujące MainWindow -

Po najechaniu myszą na przycisk z niestandardowym szablonem zmienia się również kolor, jak pokazano poniżej -

Szablon danych

Szablon danych definiuje i określa wygląd i strukturę zbioru danych. Zapewnia elastyczność formatowania i definiowania prezentacji danych w dowolnym elemencie interfejsu użytkownika. Jest głównie używany w kontrolkach elementów związanych z danymi, takich jak ComboBox, ListBox itp.

Rzućmy okiem na prosty przykład szablonu danych. Poniższy kod XAML tworzy pole combobox z szablonem danych i blokami tekstowymi.

<Window x:Class = "XAMLDataTemplate.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid VerticalAlignment = "Top">
      <ComboBox Name = "Presidents" ItemsSource = "{Binding}" Height = "30" Width = "400"> 
         <ComboBox.ItemTemplate> 
            <DataTemplate>
               <StackPanel Orientation = "Horizontal" Margin = "2">
                  <TextBlock Text = "Name: " Width = "95" Background = "Aqua" Margin = "2" /> 
                  <TextBlock Text = "{Binding Name}" Width = "95" Background = "AliceBlue" Margin = "2" /> 
                  <TextBlock Text = "Title: " Width = "95" Background = "Aqua" Margin = "10,2,0,2" />
                  <TextBlock Text = "{Binding Title}" Width = "95" Background = "AliceBlue" Margin = "2" /> 
               </StackPanel>
            </DataTemplate>
         </ComboBox.ItemTemplate> 
      </ComboBox> 
   </Grid>
   
</Window>

Oto implementacja w C #, w której obiekt pracownika jest przypisany do DataContext -

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace XAMLDataTemplate { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window {
      public MainWindow() {
         InitializeComponent(); 
         DataContext = Employee.GetEmployees(); 
      }
   }
}

Oto implementacja w C # dla klasy Employee -

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Linq; 
using System.Runtime.CompilerServices; 
using System.Text; 
using System.Threading.Tasks;

namespace XAMLDataTemplate { 
   public class Employee : INotifyPropertyChanged {
      private string name; public string Name {
         get { return name; } 
         set { name = value; RaiseProperChanged(); } 
      }
      private string title; public string Title { 
         get { return title; } 
         set { title = value; RaiseProperChanged(); } 
      }
      public static Employee GetEmployee() {
         var emp = new Employee() { 
            Name = "Waqas", Title = "Software Engineer" };
         return emp; 
      }
      public event PropertyChangedEventHandler PropertyChanged;
      private void RaiseProperChanged( [CallerMemberName] string caller = ""){
         if (PropertyChanged != null) { 
            PropertyChanged(this, new PropertyChangedEventArgs(caller)); 
         } 
      }
      public static ObservableCollection<Employee> GetEmployees() {
         var employees = new ObservableCollection<Employee>();
         employees.Add(new Employee() { Name = "Ali", Title = "Developer" }); 
         employees.Add(new Employee() { Name = "Ahmed", Title = "Programmer" });
         employees.Add(new Employee() { Name = "Amjad", Title = "Desiner" });
         employees.Add(new Employee() { Name = "Waqas", Title = "Programmer" }); 
         employees.Add(new Employee() { Name = "Bilal", Title = "Engineer" });
         employees.Add(new Employee() { Name = "Waqar", Title = "Manager" }); 
         return employees; 
      }
   }
}

Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje następujący wynik. Zawiera kombobox i kiedy klikniesz na combobox, zobaczysz, że zbiór danych, które są tworzone w klasie Employee, jest wymieniony jako elementy combobox.

Zalecamy wykonanie powyższego kodu i eksperymentowanie z nim.

Struktura XAML udostępnia kilka strategii personalizowania i dostosowywania wyglądu aplikacji. Style zapewniają nam elastyczność w ustawianiu niektórych właściwości obiektu i ponownym użyciu tych określonych ustawień w wielu obiektach w celu uzyskania spójnego wyglądu.

  • W stylach można ustawić tylko istniejące właściwości obiektu, takie jak wysokość, szerokość i rozmiar czcionki.

  • Można określić tylko domyślne zachowanie formantu.

  • Do jednego stylu można dodać wiele właściwości.

Style służą do nadania jednolitego wyglądu zestawowi kontrolek. Niejawne style służą do stosowania wyglądu do wszystkich kontrolek danego typu i upraszczają aplikację.

Wyobraź sobie, że mamy trzy przyciski i wszystkie muszą wyglądać tak samo - taka sama szerokość i wysokość, ten sam rozmiar czcionki i ten sam kolor pierwszego planu. Możemy ustawić wszystkie te właściwości na samych elementach przycisków i nadal jest to całkiem w porządku dla wszystkich przycisków, jak pokazano na poniższym diagramie.

Jednak w prawdziwej aplikacji zazwyczaj jest ich znacznie więcej, które muszą wyglądać dokładnie tak samo. Oczywiście nie tylko przyciski, ale zazwyczaj chcesz, aby bloki tekstowe, pola tekstowe i pola kombi itp. Wyglądały tak samo w całej aplikacji. Z pewnością musi być lepszy sposób, aby to osiągnąć - jest znany jakostyling. Można myśleć o stylu jako wygodnym sposobie zastosowania zestawu wartości właściwości do więcej niż jednego elementu, jak pokazano na poniższym diagramie.

Spójrzmy na przykład, który zawiera trzy przyciski utworzone w języku XAML z pewnymi właściwościami.

<Window x:Class = "XAMLStyle.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:XAMLStyle" mc:Ignorable = "d" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <Button Content = "Button1" Height = "30" Width = "80" Foreground = "Blue" 
         FontSize = "12" Margin = "10"/>
      
      <Button Content = "Button2" Height = "30" Width = "80" Foreground = "Blue" 
         FontSize = "12" Margin = "10"/>
      
      <Button Content = "Button3" Height = "30" Width = "80" Foreground = "Blue" 
         FontSize = "12" Margin = "10"/> 
   </StackPanel> 
	
</Window>

Kiedy spojrzysz na powyższy kod, zobaczysz, że dla wszystkich przycisków wysokość, szerokość, kolor pierwszego planu, rozmiar czcionki i właściwości marginesów pozostają takie same. Gdy powyższy kod zostanie skompilowany i wykonany, wyświetli następujące dane wyjściowe -

Spójrzmy teraz na ten sam przykład, ale tym razem będziemy używać style.

<Window x:Class = "XAMLStyle.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:XAMLStyle" mc:Ignorable = "d" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Window.Resources> 
      <Style x:Key = "myButtonStyle" TargetType = "Button">
         <Setter Property = "Height" Value = "30"/> 
         <Setter Property = "Width" Value = "80"/> 
         <Setter Property = "Foreground" Value = "Blue"/> 
         <Setter Property = "FontSize" Value = "12"/> 
         <Setter Property = "Margin" Value = "10"/> 
      </Style>
   </Window.Resources> 
	
   <StackPanel> 
      <Button Content = "Button1" Style = "{StaticResource myButtonStyle}"/>
      <Button Content = "Button2" Style = "{StaticResource myButtonStyle}"/>
      <Button Content = "Button3" Style = "{StaticResource myButtonStyle}"/>
   </StackPanel>
	
</Window>

Style są zdefiniowane w słowniku zasobów, a każdy styl ma unikalny identyfikator klucza i typ docelowy. Wewnątrz elementu <style> widać, że dla każdej właściwości, która zostanie uwzględniona w stylu, zdefiniowano wiele tagów ustawiających.

W powyższym przykładzie wszystkie wspólne właściwości każdego przycisku są teraz zdefiniowane w stylu, a następnie styl jest przypisywany do każdego przycisku z unikalnym kluczem przez ustawienie właściwości stylu za pomocą rozszerzenia znaczników StaticResource.

Kiedy powyższy kod zostanie skompilowany i wykonany, utworzy następujące okno, które jest tym samym wyjściem.

Zaleta zrobienia tego w ten sposób jest od razu oczywista. Możemy ponownie użyć tego stylu w dowolnym miejscu w jego zakresie, a jeśli potrzebujemy go zmienić, po prostu zmieniamy go raz w definicji stylu zamiast na każdym elemencie.

Na jakim poziomie styl jest definiowany natychmiastowo ogranicza zakres tego stylu. Zatem zakres, tj. Gdzie możesz użyć stylu, zależy od tego, gdzie go zdefiniowałeś. Styl można zdefiniować na następujących poziomach -

Sr.No Poziomy i opis
1 Poziom kontroli

Zdefiniowanie stylu na poziomie kontroli można zastosować tylko do tej konkretnej kontrolki.

2 Poziom układu

Definiowanie stylu na dowolnym poziomie układu może być dostępne tylko dla tego układu i tylko jego elementów podrzędnych.

3 Poziom okna

Definiowanie stylu na poziomie okna może być dostępne dla wszystkich elementów w tym oknie.

4 Poziom aplikacji

Zdefiniowanie stylu na poziomie aplikacji sprawia, że ​​jest on dostępny w całej aplikacji.

Zasadniczo wyzwalacz umożliwia zmianę wartości właściwości lub podejmowanie działań na podstawie wartości właściwości. Tak więc w zasadzie pozwala dynamicznie zmieniać wygląd i / lub zachowanie twojego elementu sterującego bez konieczności tworzenia nowego.

Wyzwalacze służą do zmiany wartości dowolnej właściwości, gdy spełnione są określone warunki. Wyzwalacze są zwykle definiowane w stylu lub w katalogu głównym dokumentu, które są stosowane do tej konkretnej kontrolki. Istnieją trzy rodzaje wyzwalaczy -

  • Wyzwalacze właściwości
  • Wyzwalacze danych
  • Wyzwalacze zdarzeń

Wyzwalacze właściwości

W wyzwalaczach właściwości, gdy zmiana nastąpi w jednej właściwości, przyniesie natychmiastową lub animowaną zmianę w innej właściwości. Na przykład możesz użyć wyzwalacza właściwości, jeśli chcesz zmienić wygląd przycisku, gdy wskaźnik myszy znajduje się nad przyciskiem.

Przykład

Poniższy przykład pokazuje, jak zmienić kolor pierwszego planu przycisku, gdy mysz przechodzi do jego regionu.

<Window x:Class = "XAMLPropertyTriggers.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Window.Resources>
      <Style x:Key = "TriggerStyle" TargetType = "Button">
         <Setter Property = "Foreground" Value = "Blue" />
         <Style.Triggers>
            <Trigger Property = "IsMouseOver" Value = "True">
               <Setter Property = "Foreground" Value = "Green" />
            </Trigger> 
         </Style.Triggers>
      </Style>
   </Window.Resources>
	
   <Grid>
      <Button Width = "100" Height = "70" Style = "{StaticResource TriggerStyle}" 
         Content = "Trigger"/>
   </Grid>
	
</Window>

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik -

Gdy mysz wejdzie w obszar przycisku, kolor pierwszego planu zmieni się na zielony.

Wyzwalacze danych

Wyzwalacz danych wykonuje jakąś akcję, gdy powiązane dane spełniają jakiś warunek. Przyjrzyjmy się poniższemu kodowi XAML, w którym pole wyboru i blok tekstu są tworzone z niektórymi właściwościami. Zaznaczenie tego pola spowoduje zmianę koloru pierwszego planu na czerwony.

<Window x:Class = "XAMLDataTrigger.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "Data Trigger" Height = "350" Width = "604">
	
   <StackPanel HorizontalAlignment = "Center">
      <CheckBox x:Name = "redColorCheckBox" Content = "Set red as foreground color" Margin = "20"/>
		
      <TextBlock Name = "txtblock" VerticalAlignment = "Center" 
         Text = "Event Trigger" FontSize = "24" Margin = "20">
         <TextBlock.Style>
            <Style>
               <Style.Triggers>
                  <DataTrigger Binding = "{Binding ElementName = redColorCheckBox, Path = IsChecked}" 
                     Value = "true">
                     <Setter Property = "TextBlock.Foreground" Value = "Red"/>
                     <Setter Property = "TextBlock.Cursor" Value = "Hand" />
                  </DataTrigger>
               </Style.Triggers>
            </Style>
         </TextBlock.Style>
      </TextBlock>
   </StackPanel>
	
</Window>

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik -

Gdy pole wyboru jest zaznaczone, kolor pierwszego planu bloku tekstu zmieni się na czerwony.

Wyzwalacze zdarzeń

Wyzwalacz zdarzenia wykonuje jakąś akcję, gdy uruchamiane jest określone zdarzenie. Zwykle jest używany do wykonywania niektórych animacji, takich jak DoubleAnimation, ColorAnimation itp. Poniższy blok kodu tworzy prosty przycisk. Uruchomione zdarzenie kliknięcia spowoduje rozszerzenie szerokości i wysokości przycisku.

<Window x:Class = "XAMLEventTrigger.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid>
      <Button Content = "Click Me" Width = "60" Height = "30">
         <Button.Triggers>
            <EventTrigger RoutedEvent = "Button.Click">
               <EventTrigger.Actions>
                  <BeginStoryboard>
                     <Storyboard>
                     
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Width" Duration = "0:0:4">
                           <LinearDoubleKeyFrame Value = "60" KeyTime = "0:0:0"/>
                           <LinearDoubleKeyFrame Value = "120" KeyTime = "0:0:1"/>
                           <LinearDoubleKeyFrame Value = "200" KeyTime = "0:0:2"/>
                           <LinearDoubleKeyFrame Value = "300" KeyTime = "0:0:3"/>
                        </DoubleAnimationUsingKeyFrames>
							
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Height" Duration = "0:0:4">
                           <LinearDoubleKeyFrame Value = "30" KeyTime = "0:0:0"/>
                           <LinearDoubleKeyFrame Value = "40" KeyTime = "0:0:1"/>
                           <LinearDoubleKeyFrame Value = "80" KeyTime = "0:0:2"/>
                           <LinearDoubleKeyFrame Value = "150" KeyTime = "0:0:3"/>
                        </DoubleAnimationUsingKeyFrames>
							
                     </Storyboard>
                  </BeginStoryboard>
               </EventTrigger.Actions>
            </EventTrigger>
         </Button.Triggers>
      </Button>
   </Grid>
</Window>

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik -

Teraz kliknij przycisk, a zobaczysz, że zacznie się on rozszerzać w obu wymiarach.

Jeśli jesteś zaznajomiony z debugowaniem w dowolnym języku proceduralnym (takim jak C #, C / C ++ itp.) I znasz użycie breaki spodziewasz się tego samego rodzaju debugowania w XAML, będziesz zaskoczony, wiedząc, że nie jest jeszcze możliwe debugowanie kodu XAML, tak jak w przypadku debugowania dowolnego innego kodu języka proceduralnego. Debugowanie aplikacji XAML oznacza próbę znalezienia błędu;

  • W powiązaniu danych Twoje dane nie pojawiają się na ekranie i nie wiesz dlaczego

  • Lub problem jest związany ze złożonymi układami.

  • Lub problem z wyrównaniem lub problemy z kolorem marginesów, nakładkami itp. W przypadku niektórych rozbudowanych szablonów, takich jak ListBox i pole kombi.

Debugowanie w języku XAML jest zwykle wykonywane w celu sprawdzenia, czy powiązania działają, a jeśli nie, to w celu sprawdzenia, co jest nie tak. Niestety, ustawienie punktów przerwania w powiązaniach XAML nie jest możliwe, z wyjątkiem Silverlight, ale możemy użyć okna danych wyjściowych, aby sprawdzić błędy powiązań danych. Przyjrzyjmy się poniższemu kodowi XAML, aby znaleźć błąd w powiązaniu danych.

<Window x:Class = "DataBindingOneWay.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid>
      <StackPanel Name = "Display">
         <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0">
            <TextBlock Text = "Name: " Margin = "10" Width = "100"/>
            <TextBlock Margin = "10" Width = "100" Text = "{Binding FirstName}"/>
         </StackPanel>
			
         <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0">
            <TextBlock Text = "Title: " Margin = "10" Width = "100"/>
            <TextBlock Margin = "10" Width="100" Text = "{Binding Title}" />
         </StackPanel>
      </StackPanel>
   </Grid>
	
</Window>

Właściwości tekstu dwóch bloków tekstowych są ustawione statycznie na „Nazwa” i „Tytuł”, podczas gdy właściwości Tekst pozostałych dwóch bloków tekstu są powiązane z „Imię” i „Tytuł”. Ale zmienne klasy są celowo przyjmowane jako nazwa i tytuł w klasie pracownika, które są niepoprawnymi nazwami zmiennych. Spróbujmy teraz zrozumieć, gdzie możemy znaleźć tego typu błąd, gdy pożądany wynik nie jest pokazany.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace DataBindingOneWay {
   public class Employee {
      public string Name { get; set; } 
      public string Title { get; set; }
		
      public static Employee GetEmployee() {
         var emp = new Employee() {
            Name = "Ali Ahmed", 
            Title = "Developer"
         };
         return emp; 
      }
   }
}

Oto implementacja klasy MainWindow w kodzie C # -

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace DataBindingOneWay {
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window {
      public MainWindow() {
         InitializeComponent(); 
         DataContext = Employee.GetEmployee(); 
      }
   }
}

Uruchommy tę aplikację i od razu zobaczysz w naszym MainWindow, że pomyślnie powiązaliśmy z tytułem tego obiektu pracownika, ale nazwa nie jest powiązana.

Aby sprawdzić, co się stało z nazwą, spójrzmy na okno wyjściowe, w którym generowanych jest dużo dzienników.

Najłatwiejszym sposobem znalezienia błędu jest po prostu wyszukanie błędu, a znajdziesz poniżej wymieniony błąd o treści „Błąd ścieżki BindingExpression: nie znaleziono właściwości „ FirstName ” w „ obiekcie ”„ Pracownik ”

System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName'
   property not found on 'object' ''Employee' (HashCode = 11611730)'.
BindingExpression:Path = FirstName; 
DataItem = 'Employee' (HashCode = 11611730); target element is 'TextBlock' (Name = ''); 
target property is 'Text' (type 'String')

Co wyraźnie wskazuje, że FirstName nie jest członkiem klasy Employee, więc pomaga rozwiązać tego typu problemy w aplikacji.

Kiedy zmienisz FirstName do Name ponownie zobaczysz żądane wyjście.

Narzędzia do debugowania interfejsu użytkownika dla języka XAML

Narzędzia do debugowania interfejsu użytkownika dla języka XAML zostały wprowadzone w programie Visual Studio 2015 w celu sprawdzenia kodu XAML w czasie wykonywania. Za pomocą tych narzędzi kod XAML jest przedstawiany w postaci wizualnego drzewa uruchomionej aplikacji WPF, a także różnych właściwości elementu interfejsu użytkownika w drzewie. Aby włączyć to narzędzie, wykonaj kroki podane poniżej.

  • Step 1 - Przejdź do menu Narzędzia i wybierz Opcje z menu Narzędzia.

  • Step 2 - Zobaczysz następujące okno dialogowe.

  • Step 3 - Przejdź do opcji ogólnych pod pozycją Debugowanie po lewej stronie.

  • Step 4 - Zaznacz podświetloną opcję, np. „Włącz narzędzia debugowania interfejsu użytkownika dla języka XAML”

  • Step 5 - Naciśnij przycisk OK.

Teraz uruchom dowolną aplikację XAML lub użyj następującego kodu XAML -

<Window x:Class = "XAMLTestBinding.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <StackPanel>
      <ComboBox Name = "comboBox" Margin = "50" Width = "100">
         <ComboBoxItem Content = "Green"/>
         <ComboBoxItem Content = "Yellow" IsSelected = "True"/>
         <ComboBoxItem Content = "Orange" />
      </ComboBox>
		
      <TextBox Name = "textBox" Margin = "50" Width = "100" 
         Height = "23" VerticalAlignment = "Top" Text = "{
         Binding ElementName = comboBox, Path = SelectedItem.Content, 
         Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" 
         Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}"> 
      </TextBox>
   </StackPanel>
	
</Window>

Gdy aplikacja zostanie uruchomiona, wyświetli Live Visual Tree, w którym wszystkie elementy są pokazane w drzewie.

To drzewo wizualne na żywo przedstawia pełną strukturę układu, aby zrozumieć, gdzie są umieszczone elementy interfejsu użytkownika. Ale ta opcja jest dostępna tylko w programie Visual Studio 2015. Jeśli używasz starszej wersji programu Visual Studio, nie możesz używać tego narzędzia; jednak istnieje inne narzędzie, które można zintegrować z programem Visual Studio, takie jak XAML Spy for Visual Studio. Możesz go pobrać zhttp://xamlspy.com/download. Zalecamy pobranie tego narzędzia, jeśli używasz starszej wersji programu Visual Studio.

XAML ma jedną z najpotężniejszych funkcji do tworzenia niestandardowych formantów, które bardzo ułatwiają tworzenie bogatych w funkcje i dostosowywalnych formantów. Własne kontrole są stosowane, gdy wszystkie wbudowane kontrole przewidziane przez Microsoft nie spełniają kryteria lub nie chcą płacić za 3 rd kontroli partii.

W tym rozdziale dowiesz się, jak tworzyć niestandardowe kontrolki. Zanim zaczniemy przyglądać się kontrolkom niestandardowym, przyjrzyjmy się najpierw kontroli użytkownika.

Kontrola użytkownika

Formanty użytkownika zapewniają technikę zbierania i łączenia różnych wbudowanych kontrolek razem i pakowania ich w kod XAML wielokrotnego użytku. Kontrolki użytkownika są używane w następujących scenariuszach -

  • Jeśli formant składa się z istniejących formantów, tj. Można utworzyć pojedynczą kontrolkę z wielu już istniejących formantów.

  • Jeśli formant nie potrzebuje obsługi motywów. Formanty użytkownika nie obsługują skomplikowanych dostosowań, szablonów kontroli, a także są trudne do stylizacji.

  • Jeśli deweloper woli pisać kontrolki przy użyciu modelu związanego z kodem, w którym widok, a następnie bezpośredni kod jest zapisywany za programami obsługi zdarzeń.

  • Nie będziesz dzielić kontroli nad aplikacjami.

Weźmy przykład kontroli użytkownika i wykonaj kroki podane poniżej -

  • Step 1 - Utwórz nowy projekt WPF, a następnie kliknij prawym przyciskiem myszy rozwiązanie i wybierz Dodaj> Nowy element ...

  • Step 2 - Otworzy się następujące okno dialogowe, teraz wybierz User Control (WPF) i nazwij to MyUserControl.

  • Step 3 - Kliknij przycisk Dodaj, a zobaczysz, że dwa nowe pliki (MyUserControl.xaml i MyUserControl.cs) zostaną dodane do twojego rozwiązania.

Poniżej podano kod XAML, w którym jest tworzony przycisk i pole tekstowe z niektórymi właściwościami w pliku MyUserControl.xaml.

<UserControl x:Class = "XAMLUserControl.MyUserControl" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
   mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">
	
   <Grid>
      <TextBox Height = "23" HorizontalAlignment = "Left" 
         Margin = "80,49,0,0" Name = "txtBox" VerticalAlignment = "Top" Width = "200" />
      <Button Content = "Click Me" Height = "23" 
         HorizontalAlignment = "Left" Margin = "96,88,0,0" Name = "button" 
         VerticalAlignment = "Top" Width = "75" Click = "button_Click" />
   </Grid>
	
</UserControl>

Poniżej podano kod C # zdarzenia kliknięcia przycisku w pliku MyUserControl.cs, który aktualizuje pole tekstowe.

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace XAMLUserControl {
   /// <summary> 
      /// Interaction logic for MyUserControl.xaml
   /// </summary> 
	
   public partial class MyUserControl : UserControl {
      public MyUserControl() {
         InitializeComponent(); 
      }
      private void button_Click(object sender, RoutedEventArgs e) { 
         txtBox.Text = "You have just clicked the button"; 
      } 
   }
}

Oto implementacja w MainWindow.xaml, aby dodać kontrolkę użytkownika.

<Window x:Class = "XAMLUserControl.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:control = "clr-namespace:XAMLUserControl" 
   Title = "MainWindow" Height = "350" Width = "525">
	
   <Grid>
      <control:MyUserControl/>
   </Grid>
	
</Window>

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik -

Teraz kliknij przycisk „Kliknij mnie”, a zobaczysz, że tekst pola tekstowego został zaktualizowany.

Kontrole niestandardowe

Kontrolka niestandardowa to klasa oferująca własny styl i szablon, które są zwykle zdefiniowane w programie generic.xaml. Kontrole niestandardowe są używane w następujących scenariuszach,

  • Jeśli kontrolka nie istnieje i musisz ją utworzyć od podstaw.

  • Jeśli chcesz rozszerzyć lub dodać funkcjonalność do istniejącej kontrolki, dodając dodatkową właściwość lub dodatkową funkcjonalność w celu dopasowania do konkretnego scenariusza.

  • Jeśli Twoje elementy sterujące wymagają obsługi motywów i stylizacji.

  • Jeśli chcesz współdzielić kontrolę nad aplikacjami.

Weźmy przykład niestandardowej kontroli i wykonaj kroki podane poniżej.

  • Step 1 - Utwórz nowy projekt WPF, a następnie kliknij prawym przyciskiem myszy rozwiązanie i wybierz Dodaj> Nowy element ...

  • Step 2- Otworzy się następujące okno dialogowe. Teraz wybierzCustom Control (WPF) i nazwij to MyCustomControl.

  • Step 3 - Kliknij przycisk Dodaj, a zobaczysz, że dwa nowe pliki (Themes / Generic.xaml i MyCustomControl.cs) zostaną dodane do twojego rozwiązania.

Poniżej podano kod XAML, w którym styl jest ustawiony dla kontrolki niestandardowej w pliku Generic.xaml.

<ResourceDictionary 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:XAMLCustomControls">
	
   <Style TargetType = "{x:Type local:MyCustomControl}"
      BasedOn = "{StaticResource {x:Type Button}}"> 
      <Setter Property = "Background" Value = "LightSalmon"/>
      <Setter Property = "Foreground" Value = "Blue"/>
   </Style>
	
</ResourceDictionary>

Poniżej podano kod C # dla klasy MyCustomControl, który jest dziedziczony z klasy przycisku iw konstruktorze, przesłania metadane.

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace XAMLCustomControls {
   public class MyCustomControl : Button {
      static MyCustomControl() {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), 
            new FrameworkPropertyMetadata(typeof(MyCustomControl)));
      }
   }
}

Poniżej podano implementację zdarzenia kliknięcia kontrolki niestandardowej w języku C #, która aktualizuje tekst bloku tekstu.

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace XAMLCustomControls {
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window {
      public MainWindow() { 
         InitializeComponent(); 
      }
      private void customControl_Click(object sender, RoutedEventArgs e) {
         txtBlock.Text = "You have just click your custom control"; 
      } 
   }
}

Oto implementacja w MainWindow.xaml, aby dodać kontrolkę niestandardową i TextBlock.

<Window x:Class = "XAMLCustomControls.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:control = "clr-namespace:XAMLCustomControls" Title = "MainWindow"
   Height = "350" Width = "604">
	
   <StackPanel>
      <control:MyCustomControl x:Name = "customControl" 
         Content = "Click Me" Width = "70" Margin = "10" Click = "customControl_Click"/>
      <TextBlock Name = "txtBlock" Width = "250" Height = "30"/>
   </StackPanel>
	
</Window>

Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujący wynik. Zauważ, że dane wyjściowe zawierają niestandardową kontrolkę, która jest dostosowanym przyciskiem.

Teraz kliknij dostosowany przycisk. Zobaczysz, że tekst bloku tekstu został zaktualizowany.