Artykuł

maj 20 2011
0

WPF Tutorial - obsługa kontrolek

W poprzedniej i zarazem pierwszej części tutoriala do WPF, powiedzieliśmy sobie co nieco na temat samego WPF, zawartego w nim języka XAML oraz menadżerów układów. Dziś przyszła kolej na kontrolki, bez których w GUI, nie było prawdopodobnie by niczego. Co należy rozumieć jako kontrolkę? Są to wszystkie buttony, gridy, listy, comboboxy itp. itd. Każda z kontrolek, posiada pewien wspólny zestaw właściwości, które bierze się z reguł dziedziczenia zawartych w WPFie (patrz akapit o drzewach). Oprócz tego, kontrolki cechują się własnymi właściwościami i zdarzeniami, uzależnionymi od funkcjonalności przez siebie dostarczanych, które determinują jej wygląd oraz zachowanie.

Pewną niespodzianką może być również fakt, że menadżery układów, które przedstawiłem w pierwszej części, również określane są mianem kontrolek i jak już wspomniałem wcześniej, stanowią one integralną praktycznie każdego interfejsu użytkownika.

Logical i Visual Tree

Omówienie kontrolek WPF, powinniśmy rozpocząć od logicznego i wizualnego drzewa, które wywołałem we wstępie do niniejszego wpisu. Za co są odpowiedzialne drzewa? Najprościej mówiąc, za dziedziczenie kontrolek oraz właściwości, co dobitnie pokazuje poniższy schemat::

Na rysunku, przedstawione zostało wyraźne rozróżnienie pomiędzy elementami logicznymi - kontrolkami, a ich właściwościami, które stanowią drzewo wizualne. Dowiedzmy się zatem, które drzewo jest które.

Logical Tree

Drzewo logiczne, prezentuje w głównej mierze relacje pomiędzy wszelakimi kontrolkami znajdujący się w naszym oknie, a także relacje z samym oknem, które znajduje się na samej górze. Tak sformułowane drzewo, jest odpowiedzialne za kilka istotnych rzeczy:

  • Dziedziczenie wartości właściwości - DependencyProperties
  • Obsługę zdarzeń - RoutedEvents
  • Pobieranie referencji dla zasobów dynamicznych - DynamicResources
  • Wyszukiwanie nazw elementów do bindowania - DataBinding

Najważniejszą informacją, która należy zapamiętać, jest fakt dziedziczenia właściwości oraz zdarzeń - o tym jak z tego z pożytkiem skorzystać, dowiecie się czytając kolejne akapity.

Visual Tree

Drzewo wizualne, zawiera wszystkie elementy logiczne (patrz wyżej) oraz wszystkie cechy, które pozwalają określić wygląd tychże elementów. Czyli np. obramowanie (z ang. Border), marginesy (z ang. Margin) itp., które możemy zastosować do przycisku, etykiety itd. Z tego też powodu, na drzewie wizualnym, spoczywa wielka odpowiedzialność m.in za następujące rzeczy:

  • Renderowanie elementów wizualnych
  • Propagowanie właściwości opacity - przezroczystość elementu
  • Propagowanie właściwości IsEnabled - aktywuje/bądź blokuje element
  • Propagowanie właściwości wizualnych

Ciekawym wykorzystaniem drzewa wizualnego może być zastosowanie właściwości IsEnabled. Wyobraźmy sobie, że mamy grupę przycisków umieszczoną np. w WrapPanelu (coś takiego robiliśmy w pierwszej części wpisu). W wyniku pewnego zdarzenia, chcemy zablokować wszystkie przyciski, ustawiając dla każdego właściwość IsEnabled na false. Normalnie, musielibyśmy powtórzyć, taką czynność dla każdego z przycisków.

Korzystając z Visual Tree, wystarczy ustawić taką właściwość dla naszego Wrap panelu, by wszystkie elementy, które znajdą się w jego zasięgu zostały zablokowane, czyli po prostu obdarowane odpowiednim ustawieniem właściwości IsEnabled:)

Pozycjonowanie kontrolek w układzie - podstawowe właściwości

W pierwszym wpisie, dużo miejsca poświęciłem menadżerom układu, które możemy zastosować w WPF by budować nasze GUI. Okazuje się jednak, że oprócz tego, że każdą z kontrolek możemy umieścić w pewnym panelu, to możemy jeszcze dość dokładnie określić jej właściwości takie jak np. szerokość, wysokość, wyrównanie w poziomie, wyrównanie w pionie itp. Wszystko to, umożliwia nam dokładne planowanie układu graficznego aplikacji, z możliwością dostosowywania się do zaistniałych okoliczności.

Jeśli chcemy potraktować naszą aplikację w sposób minimalistyczny, to możemy zastosować po prostu panel Canvas, zastosować pozycjonowanie relatywne, zablokować możliwość zmiany rozmiaru okna oraz ustawić szerokość i wysokość każdego z elementów. Wtedy, nasze okienko zawsze będzie wyglądać idealnie, lecz ucierpi na tym nasz użytkownik, który np. na monitorze z obsługą Full HD, będzie musiał się bawić z okienkiem przystosowanym bardziej pod rozdzielczość 800 x 600. Ale chyba nie o to nam wszystkim chodzi, prawda;)?

Jeśli chcemy jednak podejść do sprawy trochę bardziej ambitnie (wierzę, że tak:)) i chcemy udostępnić naszym użytkownikom, np. takie funkcjonalności jak:

  • Zmiana rozmiaru okna
  • Pracę z aplikacją w różnych językach
  • Wykorzystanie elastycznego GUI

To powinniśmy skorzystać raczej z innych paneli niż Canvas i skupić się uważnie na kilku kolejnych akapitach.

Ustawienia rozmiaru kontrolek

Podstawowymi właściwościami, które możemy zaaplikować każdej z kontrolek (również wszelkiej maści panelom) są Width oraz Height, reprezentujące odpowiednio szerokość i wysokość. Spójrzmy na przykład:

<Window x:Class="MyFirstWpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="500">
    <StackPanel Width="350" Height="150">
        <Button Width="200" Height="50" Content="Test" />
    </StackPanel>
</Window>

W tym przypadku, ustawiliśmy inne wymiary dla okna, panelu oraz przycisku. Wartości wysokości i szerokości, mogą być definiowane na dwa sposoby:

  • Za pomocą wartości logicznej (wartość wyrażona liczbowo)
  • Za pomocą słowa kluczowego auto - wartość domyślna. W tym wariancie, wielkość kontrolki dopasowywana jest automatycznie do jej zawartości

Oprócz standardowych wymiarów, WPF umożliwia ustawienie czterech dodatkowych właściwości, które szczególnie mogą okazać się przydatne w przypadku ustawienia wysokości/szerokości na auto:

  • MinWidth - pozwala na ustawienie minimalnej szerokości. MinWidth, oznacza że kontrolka będzie przynajmniej tak szeroka jak wartość jednostki logicznej przypisana tej właściwości
  • MaxWidth - pozwala na ustawienie maksymalnej szerokości. MaxWidth, oznacza że kontrolka będzie maksymalnie taka szeroka jak wartość jednostki logicznej przypisana tej właściwości
  • MinHeight - pozwala na ustawienie minimalnej wysokości. MinHeight, oznacza że kontrolka będzie przynajmniej tak wysoka jak wartość jednostki logicznej przypisana tej właściwości
  • MaxHeight - pozwala na ustawienie maksymalnej wysokości. MaxHeight, oznacza że kontrolka będzie maksymalnie tak wysoka jak wartość jednostki logicznej przypisana tej właściwości

Przykładowy kod, korzystający z wszystkich wymienionych wyżej właściwości:

<Window x:Class="MyFirstWpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="500">
    <StackPanel MinWidth="350" MinHeight="150">
        <Button MaxWidth="200" MaxHeight="50" Content="Test" />
    </StackPanel>
</Window>

Marginesy oraz padding

Kolejnymi właściwościami, które możemy zaaplikować naszej kontrolce są Margin oraz Padding. Pierwsza z nich, umożliwia ustawienie wartości dla marginesów naszej kontrolki. Marginesy pozwalają na odsunięcie naszej kontrolki względem sąsiadujących elementów i pojawiły się one już nie oficjalnie w pierwszej części wpisu. Padding, z kolei pozwala na odsunięcie elementów wewnątrz kontrolki, czyli np. tekstu wewnątrz przycisku. Spójrzmy na poglądowy rysunek:

W tym przypadku, wszystkie wymiary korzystają z wartości auto, całością sterują wartości margin oraz padding dla przycisku:

<Window x:Class="MyFirstWpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow">
    <StackPanel>
        <Button Content="Test" Margin="55" Padding="15" />
    </StackPanel>
</Window>

Należy tutaj zwrócić uwagę na pewien mały niuans. Jeśli uruchomimy aplikację, to okaże się, że jest ona znacznie szersza i wyższa, aniżeli widok przedstawiony na podglądzie. Dzieje się tak, ponieważ właściwość okna SizeToContent, domyślnie ustawiona jest w trybie Manual (czyli oczekiwane są logiczne wartości dla właściwości Width and Height okna). Musimy ją przestawić w tryb WidthAndHeight. Możemy to zrobić albo za pomocą okna Properties, albo dodając do znacznika Window tą właściwość ręcznie:

SizeToContent="WidthAndHeight"

Wróćmy jednak do tematu. Wartości, które zastosowaliśmy dla marginesu oraz paddingu, dotyczą wszystkich czterech krawędzi. Możemy jednak zdefiniować każdą z krawędzi z osobna, po prostu wymieniając poszczególne wartości po przecinku:

<Button Margin="L,G,P,D" Padding="L,G,P,D" />

Gdzie odpowiednie wartości to kolejno: lewa, górna, prawa i dolna krawędź. Możemy również definiować wartości horyzontalnie i wertykalnie:

<Button Margin="H,W" Padding="H,W" />

Gdzie H dotyczy wartości definiujących poziom, a W pion.

Wyrównywanie kontrolek oraz ich zawartości

Kolejną rzeczą, którą możemy zrobić z naszymi kontrolkami, jest ich pozycjonowanie względem układu oraz pozycjonowanie zawartości samych kontrolek. Za te operacje, odpowiedzialne są cztery właściwości:

  • HorizontalAlignment - pozycjonuje kontrolkę w poziomie
  • VerticalAlignment - pozycjonuje kontrolkę w pionie
  • HorizontalContentAlignment - pozycjonuje zawartość kontrolki (np. tekst) w poziomie
  • VerticalContentAlignment - pozycjonuje zawartość kontrolki (np. tekst) w pionie

Wszystkie wymienione wyżej właściwości współpracują z właściwościami Margin oraz Padding i z definicji, mogą przyjmować jedną z czterech stałych wartości:

  • Left - wyrównanie do lewej
  • Right - wyrównanie do prawej
  • Center - wycentrowanie
  • Stretch - rozciągnięcie/dopasowanie

Ponieważ użycie właściwości centrujących kontrolkę i jej zawartość jest w praktyce identyczne, to w przykładzie odniesiemy się tylko do tej pierwszej grupy. Spójrzmy na następujący kod:

<Window x:Class="MyFirstWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Button Content="button01" Grid.Row="0" Grid.Column="0" 
                HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Button Content="button02" Grid.Row="0" Grid.Column="1"
                HorizontalAlignment="Center" VerticalAlignment="Top"/>
        <Button Content="button03" Grid.Row="0" Grid.Column="2" 
                HorizontalAlignment="Right" VerticalAlignment="Top"/>
        <Button Content="button04" Grid.Row="0" Grid.Column="3" 
                HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
        <Button Content="button05" Grid.Row="1" Grid.Column="0" 
                HorizontalAlignment="Left" VerticalAlignment="Center"/>
        <Button Content="button06" Grid.Row="1" Grid.Column="1"
                HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Button Content="button07" Grid.Row="1" Grid.Column="2" 
                HorizontalAlignment="Right" VerticalAlignment="Center"/>
        <Button Content="button08" Grid.Row="1" Grid.Column="3" 
                HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
        <Button Content="button09" Grid.Row="2" Grid.Column="0" 
                HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <Button Content="button10" Grid.Row="2" Grid.Column="1"
                HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        <Button Content="button11" Grid.Row="2" Grid.Column="2" 
                HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
        <Button Content="button12" Grid.Row="2" Grid.Column="3" 
                HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
        <Button Content="button13" Grid.Row="3" Grid.Column="0" 
                HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
        <Button Content="button14" Grid.Row="3" Grid.Column="1"
                HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
        <Button Content="button15" Grid.Row="3" Grid.Column="2" 
                HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
        <Button Content="button16" Grid.Row="3" Grid.Column="3" 
                HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
    </Grid>
</Window>

Powyższy listing (trochę długi), ale prezentuje wszystkie możliwe kombinacje właściwości HorizontalAlignemnt oraz VerticalAlignment. Wizualnie prezentuje się to następująco:

Teraz możemy już rozlokować nasze kontrolki w praktycznie nieograniczony sposób;)

DataBinding

DataBinding, czyli po naszemu Bindowanie, to mechanizm, który pozwala na automatyczny transfer danych pomiędzy naszymi kontrolkami (warstwą prezentacji), a właściwą logiką programu (klasy C#). DataBinding, może działać jedno, lub dwu kierunkowo i umożliwia aktualizację danych w czasie rzeczywistym.

Co możemy bindować? Możemy np. pobierać dane z bazy danych i wyświetlać je na liście. Możemy też, bindować listę stringów, jako wartości dla ComboBoxa. Możliwe jest również bindowanie wartości jednego obiektu, z polami np. określonego formularza itd.

Jak korzystać z DataBinding? Przede wszystkim, należy ustawić źródło elementów, a każdej kontrolce/komórce, która ma korzystać z tego źródła, ustawić odpowiedni element, który będzie bindowany (czyli np. konkretne pole bazy danych, bądź właściwość obiektu). O tym jak tego dokonać, dowiecie się z jednego z kolejnych wpisów, który w całości mam zamiar poświęcić właśnie bindowaniu.

Właściwość Tag

Właściwość Tag kontrolek, jest już dobrze znana z Windows Forms. Pozwala ona nam na przechowywanie dowolnego obiektu, który będzie skojarzony z naszą kontrolką. Może to być np. string, int, czy też nasz własny obiekt:

<Button Name="btnTest" Content="Test" Tag="Lalalalala" />

Oczywiście wartość właściwości Tag, możemy również zmienić/pobrać z poziomu kodu C#:

btnTest.Tag = "Lalalalala";
string sText = btnTest.Tag.ToString();

Do czego może się przydać ta właściwość? Może ona być użyteczna, np. gdy kilka kontrolek, jest obsługiwanych przez to samo zdarzenie, które do poprawnej pracy, wymaga jakichś informacji dostarczonych przez konkretne kontrolki. Właściwość Tag, sprawdzi się idealnie.

Obsługa zdarzeń

Obsługa zdarzeń, przebiega bardzo podobnie jak w Windows Forms. Każda z kontrolek, posiada pulę zdefiniowanych zdarzeń, do których za pomocą delegacji musimy przypisać stworzone przez nas metody. Oczywiście każda z metod, musi posiadać zgodne z wybranym zdarzeniem parametry.

Tworzenie nowych metod, do obsługi zdarzeń jest banalne i możemy to zrobić na dwa sposoby. Do testów możemy wykorzystać przycisk btnTest, zadeklarowany w poprzednim akapicie.

Pierwszym sposobem, jest wykorzystanie okienka właściwości (Properties) Visual Studio. Przełączamy się na zakładkę Events i klikamy dwukrotnie na puste pole obok wybranego zdarzenia np. Click.

Efektem tego, będzie wygenerowanie następującej metody:

private void btnTest_Click(object sender, RoutedEventArgs e)
{
}

Taki sam kod, możemy również wygenerować z poziomu XAMLa. Rozpoczynamy dodawanie właściwości Click i po otwarciu cudzysłowu, Visual Studio powinien zaoferować nam pomoc. Wystarczy nacisnąć Tab, by wygenerować nowe zdarzenie:

Aby dostać się do kodu metody obsługującej dane zdarzenie, wystarczy kliknąć PPM na nazwie zdarzenia i wybrać opcję Navigate to Event Handler.

Hello World

Stworzyliśmy szkielet metody obsługującej kliknięcie na przycisk, jednak po kliknięciu na przycisk nic się nie dzieje. Warto by dodać choćby jakiś prosty Hello World:) Jak tego dokonać? Wystarczy taki prosty kod:

private void btnTest_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello World!. Kliknięto przycisk o nazwie " + 
        ((Button)sender).Name);
}

Naciśnięcie przycisku, spowoduje wyświetlenie wyżej wymienionego komunikatu. Obiekt sender, to obiekt który wywołał nasze zdarzenie. Dzięki temu, możemy pozyskać np. jego nazwę, czy też dodatkowy obiekt z właściwości Tag. Wystarczy tylko go rzutować na docelowy obiekt, czyli w naszym przypadku przycisk.

Aby MessageBox funkcjonował, musi istnieć odpowiedni using:

using System.Windows;

Zawsze możemy go dodać ręcznie, lub skorzystać z menu, które w takim przypadku wyświetla Visual Studio.

Szybki przegląd podstawowych kontrolek

WPF, posiada całkiem pokaźną kolekcję kontrolek standardowych i do tego dostarcza prostych narzędzi, które pozwalają na tworzenie nowych kontrolek i miksowanie tych, które już obecnie znajdują się w WPF. W kolejnych punktach, postaram się bardzo pokrótce przedstawić kilka kluczowych kontrolek, bez których WPF nie byłby tym czym jest teraz;)

Button

Nad przyciskiem pastwię się niemiłosiernie, już od samego początku. Dla przypomnienia, przycisk umożliwia uruchamianie określonych akcji, po obsłużeniu zdarzenia kliknięcia. Wewnątrz przycisku (Content), może znajdować się tekst, obrazek itp.

<Button Name="btnTest" Content="Test" />

Calendar

Calendar jest kontrolką, która umożliwia wyświetlenie kalendarza. Do czego może on się nam przydać? Możemy za jego pomocą pozwolić użytkownikowi wybrać żądaną datę. Dzięki temu, wiemy że data trafi do nas odpowiednio sformatowana i że użytkownik nie wprowadzi zamiast daty, żadnych nie oczekiwanych danych. Użycie kontrolki Calendar, jest banalnie proste:

<Calendar Name="calCalendar" />

CheckBox

CheckBox to innymi słowy przełącznik, który działa w trybie true/false - aktywuj/dezaktywuj. Świetnie nadaje się do wszelkiej maści ustawień, które muszą coś włączyć bądź wyłączyć. Kod:

<CheckBox Content="Zaznacz mnie!" Name="cbCheckbox" />

ComboBox

ComboBox, pozwala na tworzenie szybkich list rozwijanych. Dane do kontrolki, mogą zostać dodane bezpośrednio w XAMLu, za pomocą kodu w code-behind, czy też, za pomocą bindowania. Kod:

<ComboBox Name="cbCombo" Margin="5" 
    VerticalAlignment="Center" HorizontalAlignment="Center">
    <ComboBoxItem>Czerwony</ComboBoxItem>
    <ComboBoxItem>Zielony</ComboBoxItem>
    <ComboBoxItem>Niebieski</ComboBoxItem>
    <ComboBoxItem>Żółty</ComboBoxItem>
    <ComboBoxItem>Czarny</ComboBoxItem>
</ComboBox>

DataGrid

DataGrid, jest prawdopodobnie jedną z najważniejszych (jeśli nie najważniejszą) i najpotężniejszych kontrolek oferowanych przez WPF. DataGrid, pozwala na bindowanie danych, praktycznie z dowolnego źródła i to dwukierunkowo. Ma szereg opcji konfiguracyjnych, które powinny zadowolić największego malkontenta. Dane prezentowane są w formie tabelarycznej.

Ponieważ temat DataGrida, pojawi się jeszcze przy okazji bindowania, to w dzisiejszym wpisie, tylko szczątkowa deklaracja tej kontrolki:

<DataGrid ItemsSource="..." AutoGenerateColumns="False">
    <!-- ... -->
</DataGrid>

Image

Kontrolka Image, pozwala na wyświetlanie obrazków. Wyświetlany obrazek, ustalamy za pomocą właściwości Source. Możemy to zrobić za pomocą okna Properties, dzięki czemu Visual Studio zaimportuje wybrany obrazek do zasobów aplikacji i ustawi odpowiednią wartość dla właściwości. Warto również ustawić Tooltip, który wyświetli dymek z informacją dla naszego obrazka:

<Image Source="/MyFirstWpfApplication;component/Images/IMG_0065.JPG" 
ToolTip="Niebo" />

Label

Label jest jedną z najprostszych kontrolek. Pozwala na wyświetlanie prostych tekstów (etykiet) i z reguły używany jest do opisu innych kontrolek np. TextBoxa. Spełnia zatem identyczną rolę jak Label znany choćby z języka HTML.

<Label Content="Lalalala" />

ListView

ListView, jest często wykorzystywany alternatywnie do DataGrida. Domyślnie jest on wykorzystywany do listowania elementów i nie musi mieć wcale postaci tabelarycznej. Jednak bardzo często używany jest właśnie z połączonym widokiem GridView, dlatego staje się łudząco podobny do DataGrida. ListView nie pozwala na edycję elementów umieszczonych w kontrole, tak jak ma to miejsce w DataGridzie. O ListView, powiemy sobie więcej przy okazji Bindowania. Teraz krótki zarys kodu:

<ListView ItemsSource="...">
    <GridView>
        <!-- definicja kolumn -->
    </GridView>
</ListView>

Progressbar

Progressbar, umożliwia wyświetlanie paska postępu. Jego aktualną wartość, ustawiamy za pomocą właściwości Value. Progressbar, posiada całkiem sporą liczbę opcji. Możemy m.in. zmienić domyślne minimum (1) i domyślne maksimum (100):

<ProgressBar Value="55" Minimum="1" Maximum="100" />

TextBox

Ostatnią kontrolką, którą chciałem dziś opisać jest TextBox. TextBox pozwala na wprowadzenie tekstu do naszej aplikacji przez użytkowników (O kontrolce wspominałem już trochę wyżej przy okazji opisu etykiety). Przykładowa implementacja:

<TextBox Name="txtField" HorizontalAlignment="Center" 
VerticalAlignment="Center" Width="100"/>

Podsumowanie

W dzisiejszym wpisie, starałem się Wam przekazać trochę informacji na temat kontrolek. Powiedzieliśmy sobie m.in. na temat:

  • Drzewa logicznego i wizualnego
  • Pozycjonowaniu kontrolek w układzie wizualnym
  • Wykorzystaniu podstawowych właściwości komórek
  • Bindowaniu danych
  • Obsługi zdarzeń
  • Poznaliśmy kilka najważniejszych kontrolek

Oczywiście informacje przedstawione w niniejszym wpisie to tylko zarys informacji, jakie powinniśmy wiedzieć na temat kontrolek wykorzystywanych w WPFie. Myślę jednak, że wpis jest na tyle kompletny, że pozwoli każdemu przynajmniej zrozumieć realia jakimi rządzą się WPFowe kontrolki. Jak to się mówi - najtrudniej zacząć;) Niech ta optymistyczna fraza przyświeca Wam w oczekiwaniu na kolejne części tutoriala.

Jeśli podoba Ci się ten wpis, sprawdź inne części tutoriala WPF.

Poprzednia część | Następna część

Data ostatniej modyfikacji: 28.08.2013, 14:32.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus