Guardy i Pattern Matching, czyli czym zauroczył mnie Haskell, a brakuje mi tego w C#

Ostatnio w kręgu moich zainteresowań pojawił się język Haskell. Jest to język czysto funkcyjny o silnym typowaniu, którego premiera datowana jest na rok 1990, czyli aż dekadę wcześniej niż C#. Składnia języka przypomina inne funkcyjne języki programowania jak np. F#. Nie zagłębiając się zbytnio w niuanse języka Haskell bardzo spodobały mi się w nim dwie rzeczy.

Pierwsza jest zbyt prosta, żeby poświęcić jej cały artykuł. To leniwe wartościowanie. W Haskell-u rozwiązano to inaczej niż w C#, zamiast ręcznie decydować co powinno być „Lazy”, a co nie. Leniwe wartościowanie jest stosowane zawsze, bez potrzeby dopisywania czegokolwiek w kodzie.

Drugą, dużo bardziej interesującą cechą języka Haskell są Guardy i Pattern Matching. Nie jest to cecha tylko tego języka, ale również wielu innych języków funkcyjnych, jednak mi w oczy ich zalety rzuciły się właśnie przy okazji poznawania języka Haskell.

Czym są Guardy i Pattern Matching najłatwiej będzie zrozumieć na przykładzie, a więc do dzieła ;)
Przykłady pochodzą ze strony:
http://learnyouahaskell.com/syntax-in-functions

  • Guards (pl. strażnicy)
  • guards

    Pierwsza linijka zawiera deklarację metody bmiTell wraz z typami jakie przyjmuje i zwraca (jak już wcześniej wspominałem, język Haskell jest językiem silnie typowanym). Magia dzieje się dalej. Jak się pewnie domyślasz bmi jest parametrem. Zaś pionowe kreski od których rozpoczynają się kolejne linie to właśnie Guardy. W zależności od wartości parametru bmi otrzymamy odpowiedniego stringa. Oczywiście jest to tylko prosty przykład, guardy mogą być dużo bardziej rozbudowane. Jeśli jednak nie chcemy tworzyć wielolinijkowych metod albo zależy nam na większym odseparowaniu od siebie poszczególnych operacji powinniśmy skorzystać z PatternMatchingu.

  • Pattern Matching
  • pattern matching
    Prosty przykład użycia pattern matchingu w języku Haskell. Jak widać jego funkcjonalność jest zbliżona do tej, którą oferują Guardy. Z tą różnicą, że mamy tutaj do czynienia już nie z tylko jedną, a kilkoma funkcjami.

    pattern matching silnia
    I jeszcze jeden przykład, tym razem obliczanie silni.

    Zalety takiego rozwiązania

  • Oczywiście zastosowanie guardów nie dodaje nic nowego czego w języku C#, by dotychczas nie było. Jedyną zaletą guardów w tym przypadku jest (przynajmniej według Mnie) dużo ładniejszy zapis niż w przypadku gdy użylibyśmy instrukcji switch-case lub if-else
  • Zupełnie inaczej jest zaś z zastosowaniem Pattern-Matching-u, daje on nam możliwość przeniesienia polimorfizmu/przeciążania metod na jeszcze niższy poziom – zależny od wartości parametrów. A to pozwala np. na usunięcie z kodu if-ów i switchy do wybierania konkretnej klasy po jakieś wartości enum (fabryka). Konstrukcje w stylu switch(enum)-case mogłyby odejść zupełnie do lamusa.


  • Jaka jest na to odpowiedź twórców języka C#?
    I tutaj zaskoczenie, po tym jak zachwyciłem się Pattern Matchingiem i Guard-ami w języku Haskell, postanowiłem zrobić resarch i uwaga, jest w wersji C# 7 pojawi się Pattern Matching!

    Zerknijmy zatem w przykład.
    Przykłady pochodzą ze strony:
    https://www.kenneth-truyers.net/2016/01/20/new-features-in-c-sharp-7/

    pattern matching w csharp

    Na pierwszy rzut oka wydaje się, że wszystko świetnie, po 16 latach, język C# wreszcie doczeka się Pattern Matchingu. Ale czy użycie instrukcji switch-case w przykładzie jest celowe czy może implementacja będzie nierozłączna z używaniem kolekcji warunkowych?

    Rozważmy sobie jeszcze jeden przykład.
    csharp bez pattern matchingu

    Zagadka jest bardzo prosta. Która z metod zostanie wykonana? W tym momencie (C# 6) odpowiedź wydaje się być prosta, będzie to oczywiście metoda Print(Geometry). Co jeśli jednak zastosowalibyśmy pattrern matching. Wtedy powinna wykonać się metoda Print(Square)?

    Na odpowiedź musimy jeszcze trochę poczekać. Najbardziej prawdopodobne wydaje się, że PatternMatching będzie na poziomie wartości parametrów, a na poziomie klas zostanie on ograniczony jedynie do przypadku z przykładu. Szkoda, bo to oznacza, że zostaniemy jeszcze trochę w świecie pisania instrukcji warunkowych, bo częściowa alternatywa jaką w tej chwili jest użycie dynamic zamiast interfejsu, niestety jest zbyt wolna (instrukcja warunkowa wykona się dużo szybciej niż pierwsze użycie dynamic).

    Edit. Pattern Matching prawdopodobnie nie pojawi się w 7 wersji C#, jego wprowadzenie zostało przesunięte.

    Własne przemyślenie
    Poprzez styczność z językami funkcyjnymi w ostatnim czasie naszło mi na myśl pewne stwierdzenie. Języki obiektowe zostały stworzone, by podnosić pewnie nietrywialne (no może trochę przesada z tą nietrywialnością) problemy na poziom obiektowości i rozwiązywać je w prosty sposób, zaś języki funkcyjne dają nam narzędzia, żeby te same problemy rozwiązywać jak najłatwiej już na poziomie funkcji ;)

    Ciekaw jestem waszych opinii. Zapraszam do komentowania. Jeśli zaś spodobał Ci się ten wpis i chciałbyś odwiedzać blog pasja-programowania częściej zapraszam do polubienia fanpage’a www.facebook.com/Pasja-programowania-1649374605334405

    Opublikowano Bez kategorii | Otagowano , , , , | 2 komentarzy

    Jak szybko wygenerować connection string bez dodatkowego oprogramowania

    Wstęp
    Ostatnio zostałem poproszony o pomoc w uzyskaniu connection string do bazy znajdującej się lokalnie na pewnym komputerze. Zadanie to było o tyle utrudnione, że oprócz serwera baz danych, nie było na nim praktycznie żadnego oprogramowania, które mogłoby mi w tym pomóc. Bezpośrednia podłączenie do serwera z mojego komputera było niemożliwe.

    Po krótkim przeglądzie tego, co w Internecie znalazłem wiele różnych odpowiedzi, ale niemal wszystkie wiązały się z instalacją dodatkowego oprogramowania. Od małych programów typu tester połączenia z bazą danych, aż po porady skorzystania z Visual Studio, co kompletnie mijało się z celem. Na szczęście natrafiłem na wpis mówiący o tym, jak z poziomu systemu Windows w bardzo prosty sposób z użyciem notatnika uzyskać połączenie z bazą danych oraz nasz upragniony connection string.

    Jak wygenerować connection string z pomocą notatnika
    Na początku należy utworzyć pusty plik tekstowy (nazwa dowolna) i zmienić jego typ na udl. o dwukrotnym kliknięciu uruchomiony zostanie program o nazwie Właściwości łącza danych.

    Dostawca

    Pierwszym krokiem będzie przejście do zakładki Dostawca i sprawdzenie, czy wybrany domyślnie dostawca jest tym, którego byśmy oczekiwali. Po wybraniu dostawcy w zakładce Połączenie możemy kliknąć przycisk odśwież i po chwili powinny pojawić nam się dostępne lokalnie serwery baz danych. Jeśli nie pojawi się żaden serwer bazy danych, ale znamy jego nazwę, można ją wpisać również ręcznie (taki przypadek może wystąpić m.in. przy próbie połączenia z serwerem Oracle). Następnie wybieramy sposób uwierzytelniania oraz bazę danych, z którą chcemy się połączyć.

    Połączenie

    Teraz wystarczy jedynie sprawdzić, czy konfiguracja jest prawidłowa, klikając przycisk Testuj połączenie. Jeśli połączenie testowe udało się, możemy już wyjść z programu.

    Połączenie powiodło się

    Aby uzyskać connection string, wystarczy jedynie zmienić typ pliku na txt lub otworzyć jego zawartość w notatniku (lub innym edytorze tekstowym). W ostatniej linijce znajduje się nasz upragniony connection string. Jeśli chcemy przetestować połączenie w naszym programie, wystarczy tylko skopiować wygenerowany tekst z pominięciem znacznika provider.

    connection string

    Po raz kolejny okazuje się, że potrzeba jest matką wynalazków, a najlepsze rozwiązania to te najprostsze. Jeśli doszedłeś do końca wpisu to dzięki za uwagę i zapraszam na fanpage pasja-programowania, dzięki czemu będziesz miał łatwiejszy dostęp do nowych wpisów.

    Fanpage Pasja-programowania

    Opublikowano Bez kategorii | 1 komentarz

    „Nie studia, lecz chęć szczera zrobią z Ciebie programmera”, czyli rzecz o studiowaniu.

    Wprowadzenie
    Na grupach dotyczących programowania (mowa tutaj głównie o grupach Facebookowych) bardzo często pojawia się pytanie czy warto iść na studia. Zwykle pod takim postem pojawia się kilkanaście, może nawet kilkadziesiąt komentarzy. Przez pewien okres masochistycznie czytałem te wszystkie odpowiedzi, aż zaczęło mnie to pytanie do tego stopnia irytować, że od pewnego czasu skutecznie pomijam tego typu wpisy. W końcu sam postanowiłem zmierzyć się z tym tematem głównie dlatego, że właśnie mój czas na studiach nieubłaganie dobiega końca. Tak więc do dzieła, oto moja krótka historia ;)

    Wstęp
    Na wstępie chciałbym odpowiedzieć sam przed sobą na kilka pytań.Pierwsze, które ciśnie mi się na usta to czy programowania można nauczyć się samemu? Odpowiedź brzmi – tak i na tym mój artykuł w sumie mógłby się zakończyć, ale spróbujmy wgryźć się w ten temat głębiej. Czy można być dobrym programistą bez ukończenia studiów? Czy studia w takim razie w jakikolwiek sposób pomagają w zostaniu programistą? Jeśli pomagają to w jaki sposób? Moim subiektywnym zdaniem odpowiedź na każde z tych pytań brzmi, tak.

    W takim razie co dały mi te studia? Na samym początku mi i moim kolegom oraz koleżankom dały podstawy. Jak dziś pamiętam pierwszy wykład z Podstaw Programowania, na którym dostaliśmy do ręki 4 proste zadania. Trzeba było przedstawić w wybranym przez siebie języku tworzenie oraz operacje dodawania i usuwania elementów tablicy, listy, kolejki oraz stosu. Wśród młodych studentów były już osoby, które pracowały jako programiści (np. Front-Endowcy czy programiści PHP), a jednak mało kto napisał cokolwiek na swojej kartce (tak, zadania były do rozwiązania na kartce). Z biegiem czasu chcąc czy nie wszyscy musieli się nauczyć jak stworzyć każdą z tych kolekcji i to własnoręcznie implementując odpowiednie struktury i operacje (bez użycia gotowych bibliotek).

    Co dają studia?
    Na pewno dają dobre podwaliny pod to, żeby stać się programistą w przyszłości i wąską wiedzę specjalistyczną, która może oczywiście się nigdzie nie przydać programiście Front-Endowemu, ale może być ważna np. w kontekście zadań optymalizacyjnych w back-endzie. Należy pamiętać, że studia to są także wymagania, potrzeba regularnego rozwoju i to nie przypadek, że na najlepszych uczelniach technicznych w Polsce po pierwszym semestrze bądź roku nawet połowa osób zostaje skreślona z listy studentów.

    Pierwszy semestr za nami, co dalej?
    Dalej tylko „gorzej” ;) Dochodzą takie przedmioty jak programowanie obiektowe, funkcyjne, logiczne, mikroprocesorowe, paradygmaty programowania, języki formalne, automaty i wiele, wiele innych. Należy pamiętać także, że studia informatyczne to nie tylko programowanie (a już na pewno nie obiektowe), ale też sieci, bezpieczeństwo systemów informatycznych, zarządzanie projektami, bazy danych, hurtowanie danych czy matematyka i fizyka. To co może być wadą studiów czyli zbyt duża liczba zagadnień do ogarnięcia jest także ich zaletą, bo w trakcie studiów poznając te wszystkie zagadnienia mamy przegląd tego co lubimy bardziej, a co mniej i sami możemy wybrać co tak naprawdę chcemy robić w przyszłości. Unikając przy tym pytania, który język programowania jest najlepszy, bo wcale programistami zostać po studiach nie musimy.
    Ps. Dla zadających sobie to pytanie polecam artykuł i infografikę znajdującą się pod tym linkiem: carlcheo.com/startcoding

    Czego studia mnie nie nauczyły?!
    Na pewno dzięki nim nie poznałem współcześnie używanych narzędzi i technik programowania obiektowego. Wzorce projektowe czy architektoniczne to też coś co na moich studiach „jakby” nie istniało. Języki z którymi miałem styczność, a było ich pewnie kilkanaście to tylko „liźnięcie tematu”. Chociaż tutaj wiedza o tym jak można coś wykonać w językach programowania logicznego czy funkcyjnego przydaje się do dzisiaj nawet w językach obiektowych, które coraz szerzej korzystają z paradygmatów innych metod programowania niż obiektowe. Mimo, że na studiach wykonałem wiele projektów, doświadczenie, które zbieram w pracy jako programista jest nieporównywalnie większe niż przy uczelnianym projekcie.

    Czy po studiach łatwiej znaleźć pracę?
    Mi się ta sztuka udała na początku 3. roku studiów. Mimo, że studentem byłem raczej średnim ;) Na jednej rozmowie zdarzyło mi się nawet dzięki studiom ominąć test sprawdzający moją wiedzę programistyczną (uznano, że moja uczelnia ma wystarczają renomę, żeby zrezygnować z przeprowadzenia testu). Wielu moim kolegom także udało się znaleźć pracę jeszcze w trakcie studiów. Niestety nie jest tak różowo jakby mogło się wydawać, równie wielu moich znajomych mimo świetnych ocen, nadal nie znaleźli zatrudnienia mimo prób. Co jest tego przyczyną? Moim zdaniem, praca programisty wymaga czegoś więcej niż wiedzy zdobytej na studiach. W pewnym momencie trzeba sobie obrać jakiś kierunek w którym chce się podążać, poświęcić trochę swojego wolnego czasu i spróbować swoich sił. Parafrazując „Nie studia lecz chęć szczera zrobi z Ciebie programmera”

    Podsumowanie
    Studia informatyczne to z pewnością nie jest szkoła programowania. Dają podwaliny pod to, żeby zostać programistą, ale nie jest to ich główna rola. Niestety (przynajmniej moje studia) nie są wystarczające, żeby stać się „koderem” z krwi i kości. Ja jednak nie żałuje czasu spędzonego na uczelni i szczerze polecam wybranie tej ścieżki rozwoju.

    Opublikowano Bez kategorii | Otagowano | 1 komentarz

    Jeszcze bardziej dynamiczne tworzenie zapytań do bazy (LinqKit)!

    Zacznijmy od tego, że ostatnio przeczytałem artykuł jednego z naszych kolegów programistów na temat dynamicznego tworzenia zapytań do EntityFramework. Link tutaj

    Artykuł fajny, rozwiązuje problem z którym Ja osobiście mierzę się dość często, ale od czasu przeczytania tego artykułu mam ogromną potrzebę pochwalenia się jak do tego problemu podchodzę ja. Tym bardziej, że uważam moje rozwiązanie za lepsze. Najlepiej różnicę będzie widać jeśli oprę się więc o ten sam przykład.

    Zacznijmy może od problemu. Czasem chcemy zbudować zapytanie, które zależne jest od jakiegoś parametru. Prosty przykład.

    public List GetProductsHiddenOnMondayAndTuesday( )
    {
    var query = products.Where(p => p.Available == true);
    if (DateTime.Now.DayOfWeek == DayOfWeek.Monday)
    query = query.Where(p => p.HiddenOnMondays == false);
    if (DateTime.Now.DayOfWeek == DayOfWeek.Tuesday)
    query = query.Where(p => p.HiddenOnTuesday == false);

    return query.ToList();
    }

    Jak widać nie jest to zbyt ładny kod dla tak trywialnego problemu, a często przychodzi nam walczyć z przykładami o wiele bardziej skomplikowanymi.

    Rozwiązanie problemu napisane w przytoczonym artykule polega na utworzeniu metody rozszerzeń do IQueryable.

    public static IQueryable TodayIs(this IQueryable query, DayOfWeek day)
    switch (day)
    {
    case DayOfWeek.Monday:
    return query.Where(p => p.HiddenOnMonday == false);
    case DayOfWeek.Tuesday:
    return query.Where(p => p.HiddenOnTuesday) == false);
    case DayOfWeek.Wednesday:
    return query.Where(p => p.HiddenOnWednesday == false);
    //etc.
    }

    Jest to oczywiście dużo ładniejsze rozwiązanie od tego w przykładzie, ale czy najlepsze? Sam autor pisze, że „typ IQueryable wymaga ostrożności i generalnie nie powinien być wyprowadzany poza repozytorium/inną warstwę dostępu do danych”. Dla Mnie osobiście pisanie takiej metody rozszerzonej jest też trochę nadużyciem, bo co jeśli byśmy chcieli wybrać np. wtorki i środy, lub jeszcze inną konfigurację? albo jak wybierać dla jednego LUB drugiego dnia?

    Na ratunek przychodzi nam biblioteka LinqKit i klasa PredicateBuilder. Klasa ta została wprost stworzona do wspomagania budowania zapytań, które podlegają filtrowaniu po wielu parametrach. Najłatwiej będzie zrozumieć to na przykładzie.

    Expression<Func> predicate = PredicateBuilder.True();
    predicate = predicate.And(x => x.Available == true)
    .And(x => x.HiddenOnMondays == true)
    .Or(x => x.HiddenOnTuesday == true);

    Najpierw tworzymy obiekt predicate, jest to expression dla zmapowanej tabeli Product. Później tworzymy serię warunków, które muszą spełnić fitrowane obiekty. Dodatkowym atutem budowania zapytań jest istnieje metody Or (alternatywa logiczna). Warunki już mamy, teraz musimy jeszcze je wykorzystać.

    public List GetFilteredProducts(Expression<Func> expression)
    {
    var query = products.AsExpandable().Where(expression);
    return query.ToList();
    }

    Jest to przykład użycia w klasie Dao produktów. Typ expression można przekazać jako parametr i użyć go wprost w metodzie where. Żeby jednak można było użyć expression potrzebne jest jeszcze dodanie AsExpandable.

    Jak widać użycie PredicateBuildera jest banalnie proste. Ważne jednak, żeby go nie nadużywać. Gdzie go więc używać? Najprościej będzie w połączeniu z zapytaniami pokroju GetFilteredSomething. Gdy używamy EntityFrameworka do połączenia z bazą danych często w Dao tworzy się wiele metod ze „sztywnymi filtrami”, możemy je zastąpić albo jedną GetFiltered i przekazywać jej kryteria z innej warstwy albo wydzielając metodę jak w przykładzie powyżej, a precyzować filtry w innych metodach dao.
    Gdzie go zaś nie używać? Tam gdzie pytania są na tyle proste i nie zależą od wielu parametrów, wtedy użycie PredicateBuildera będzie nadużyciem. Jeśli zaś korzystamy z nHibernate’a, który jest jednak dużo bardziej dojrzałym frameworkiem od EF to bardziej naturalne będzie wykorzystanie Criteria Queries, które daje nam sam framework, tutaj PredicateBuilder może okazać się zbędne.

    Jeśli spodobał Ci się ten artykuł to zapraszam do polubienia fanpage-a, na którym zawsze znajdziesz informacje o nowościach na blogu ;)
    https://www.facebook.com/Pasja-programowania-1649374605334405

    Opublikowano Bez kategorii | Otagowano , , | 3 komentarzy

    Czy interfejs może zawierać implementację metody, czyli trochę hackowania

    Język C# w całej swojej świetności ma również masę ograniczeń, oczywiście wszystko dla naszego dobra ;) Jednym z takich ograniczeń jest dziedziczenie maksymalnie po tylko jednej klasie (ale za to po wielu interfejsach). Co czasem może okazać się nie lada wyzwaniem ;) Zapraszam więc do lektury.

    Najczęstszym i najłatwiejszym rozwiązania problemu niemożności dziedziczenia po wielu klasach jest zamiana dziedziczenia na kompozycję (czy to jednej z klas po których chcieliśmy dziedziczyć czy obu/więcej). Innym równie prostym rozwiązaniem jest stworzenie odpowiedniej hierarchii klas. Najłatwiej będzie pokazać to na przykładzie.

    A chce dziedziczyć po B oraz C.
    B C
    | /
    A

    Rozwiązaniem może być np.
    C
    |
    B
    |
    A

    W ten sposób A dziedziczy zarówno, po B jak i C. Niestety nie zawsze możemy/powinniśmy skorzystać z takiego rozwiązania, szczególnie jeśli klasy B lub C dziedziczą już po jakiś innych klasach (zbytne skomplikowanie) lub klasy B i C są klasami, które kolokwialnie mówiąc, nie powinny mieć ze sobą nie wspólnego. W pewnych kontekstach klasa A mogłaby się okazać zbędna, ponieważ klasa B mogłaby ją w pełni zastąpić.

    To tylko jeden z wielu problemów jakie można napotkać i pewnie napotkamy nieraz w świecie programowania obiektowego i używania klas. Na całe szczęście istnieje „częściowa alternatywa” dla używania klas jaką są interfejsy.

    Wśród wielu różnic między klasami, a interfejsami, które pewnie doskonale znasz jedną z najważniejszych, a jeśli nie najważniejszą jest to, że interfejsy w odróżnieniu od klas mogą zawierają jedynie deklaracje metod, a nie ich implementację (oczywiście są jeszcze klasy i metody abstrakcyjne, akcesory itd. w tym artykule skupię się jednak na tej różnicy). Więc cóż nam po tym, że możemy skorzystać z wielu interfejsów, jeśli w każdej takiej klasie, musimy tworzyć odrębną implementację tychże interfejsów. Może i pewnie często powoduje to łamanie zasady DRY.

    Ale czy na pewno każda klasa musi posiadać własną implementację interfejsu? Czy interfejs nie może zawierać pełnoprawnej metod z jej implementacją? Jak się okazuje nie do końca. W tym przypadku na ratunek przychodzą nam metody rozszerzeń (nazywane także metodami rozszerzającymi albo rozszerzonymi).

    Zacznijmy od tego czym są metody rozszerzeń. Tutaj posłużę się cytatem z MSDN.

    Metody rozszerzenia umożliwiają „dodawanie” metod do istniejących typów bez konieczności tworzenia nowego typu pochodnego, ponownej kompilacji lub modyfikowania oryginalnego typu w inny sposób. Metody rozszerzenia stanowią specjalny rodzaj metod statycznych, ale są wywoływane tak, jakby były metodami wystąpień w typie rozszerzonym. W przypadku kodu klienta napisanego w języku C# i Visual Basic nie istnieje żadna widoczna różnica między wywołaniem metody rozszerzenia a wywołaniami metod, które faktycznie są zdefiniowane w typie.

    Jak się okazuje twórcy języka C# zostawili małą furtkę pozwalającą na tworzenie metod rozszerzeń również dla interfejsów. Co ciekawsze nie jest to jakby się wydawało przeoczenie programisty, a celowy zabieg z którego przywilejów korzystamy na co-dzień wszyscy, używając jednej z najpopularniejszych bibliotek platformy .Net! Ten smaczek zostawimy sobie jednak na koniec artykułu ;)

    Ale najpierw trochę kodu.

    TestInterface

    Test class

    extension

    Main

    Myślę, że kod jest na tyle prosty, że nie ma potrzeby tworzenia do niego jakiegoś szczegółowego opisu. W skrócie, tworzymy interfejs oraz przykładową klasę, która zawiera własną implementację metody interfejsu. Następnie dodane zostają dwie metody rozszerzeń dla interfejsu (warto zwrócić uwagę, że jedna z metod jest taka sama jak zadeklarowana w interfejsie i zaimplementowana w klasie). No i w końcu testujemy ;)

    main result

    Jak pewnie zauważyłeś wykonała się jedna z metod rozszerzenia oraz metoda, której implementacja jest w klasie TestClass. Czemu tak się stało? Odpowiedź jest bardzo prosta, twórcy uznali, że metoda rozszerzona nie może być bardziej ważna niż metoda, która znajduje się bezpośrednio w klasie.

    Do czego można zastosować taką metodę rozszerzoną? Pewnie wielu głównie starszych i bardziej doświadczonych programistów gotowa jest uznać, że korzystanie z takiego rozszerzenia to wręcz zbrodnia na programowaniu obiektowym. Moje zdanie zostawię dla siebie, ale myślę, że co do przydatności tego rozwiązania przekonać może jedynie fakt, że … metody rozszerzeń dla interfejsów znalazły zastosowanie w Linq. Pozwoliło to na nietworzenie z klas implementujących interfejs IEnumerable ośmiotysięczników kodu, nie ingerowanie zupełnie w istniejący już kod, a także z marketingowego punktu widzenia stworzenie odrębnego bytu jakim jest Linq.

    PS. Mimo, że korzystałem z dobrodziejstwa metod rozszerzeń od dawna, przyznaje, że nigdy nie zastanowiło mnie czemu IEnumerable i Linq są w innych namespace-ach.
    Jeśli spodobał Ci się ten artykuł to zapraszam do polubienia fanpage-a, na którym zawsze znajdziesz informacje o nowościach na blogu ;)
    https://www.facebook.com/Pasja-programowania-1649374605334405

    Opublikowano Bez kategorii | 8 komentarzy

    Kurs MVVM #5 Aplikacja wielojęzyczna

    W tej części kursu dowiesz się jak stworzyć aplikację wielojęzyczną wykorzystując bindowanie.

    Jako przykład stworzymy sobie formularz mini-formularz. Zaczynamy od stworzenia plik zasobów (ang. Resources File) w dwóch wersjach, domyślna – Polska i Angielska. Aby to zrobić do projektu dodajemy nowy element typu resx jak na obrazie poniżej.

    Add new item resource

    Plik ten wykorzystamy jako słownik domyślnego języka. Otwieramy nowo utworzony plik i dodajemy do niego kilka wpisów. W polu name wpisujemy klucz, który będzie używany w aplikacji, a value to oczywiście wartość, którą otrzymamy. Zmieniamy także pole Access Modifier z domyślnego internal na public.

    resx default pl

    Dodajemy jeszcze jeden plik resx do naszego projektu. Tutaj należy pamiętać, żeby nazwa pliku była taka sama jak nazwa pierwszego pliku zasobów z tą różnicą, że po nazwie dopisujemy kropkę i kod języka. Moja nazwa wygląda tak.

    resx en-us

    I wypełniamy go odpowiednimi wartościami.

    resx en-us values

    Skoro mamy już dane, przejdźmy do stworzenia widoku. Mój mini-formularz wygląda tak.

    view

    Jak widać wystarczy skorzystać ze statecznego bindowania do pola w słowniku. Niech nie zmyli Cię brak słowa binding, jest to po prostu skrócony zapis. Zapis pełny wyglądać może np. tak {Binding Source={x:Static StaticField}}. Zaś jeśli wejdziemy w plik designera zobaczymy, że wygenerowane zostały statyczne akcesory.

    Teraz, żeby sprawdzić czy nasz przykład na pewno działa wystarczy zmienić Thread.CurrentThread.CurrentCulture oraz Thread.CurrentThread.CurrentUICulture

    Ja zrobiłem to dodając wpis do app.config i zmieniając „Culture” w pliku App.xaml.cs

    app config

    app setting

      Podsumowanie:

    • Bindowanie pól (w rozumieniu field, property etc.) statycznych możemy wykorzystywać nie tylko gdy korzystamy z pól „słownika”, ale oczywiście wszystkich pól statycznych.
    • Pliki typu resx, nazywają się plikami zasobów, a nie słownikami nie tylko dlatego, że słowo dictionary jest już zajęte w języku C#, a dlatego, że pozwalają one na przechowywanie różnych zasobów. Są to m.in. obrazy, ikony, pliki audio, a także inne pliki dowolnego typu.
    • Jeśli jesteś zbyt leniwy :D lub popełniłeś błąd podczas tworzeniu własnej implementacji aplikacji wielojęzycznej, możesz skorzystać z mojego przykładu tutaj.
    Opublikowano Bez kategorii | 3 komentarzy

    Kurs MVVM #4 DataTemplateSelector

    Wstęp
    W poprzedniej części kursu dowiedzieliśmy się jak zbindować kolekcję danych. Dzisiaj rozszerzymy sobie to o możliwość bindowania kolekcji, która zawiera różne dane albo zawiera elementy, które chcielibyśmy przedstawić w różny sposób. Do tego posłuży nam DataTemplateSelector. Jeśli mój opis jest zbyt zagmatwany polecam zapoznać się z tym.
    https://msdn.microsoft.com/pl-pl/library/system.windows.controls.datatemplateselector(v=vs.110).aspx

    Zadanie
    Utwórz galerię zdjęć w formie listy (ListView), która zawierać będzie obiekty typu GalleryItem i PhotoItem, ale znajdującej się w jednej kolekcji. Dla ułatwienia obie klasy dziedziczą po jednym (ale pustym :P) interfejsie IGalleryItem. Oznacz w wybrany przez Ciebie sposób, że obraz w galerii jest obrazem albo zdjęciem.

    Interfejs IGalleryItem

    public interface IGalleryItem
        {
        }
    

    Klasa GalleryItem

    public class GalleryItem : IGalleryItem
        {
            public BitmapImage Image { get; set; }
            public string Text { get; set; }
            public bool IsActive { get; set; }
        }
    

    Klasa PhotoItem

    public class PhotoItem: IGalleryItem
        {
            public BitmapImage Photo { get; set; }
            public string Description { get; set; }
        }
    

    Zaczniemy tradycyjnie od widoku. Sama kontrolka ListView nie będzie się różnić znacznie od tej z 3 części kursu. Jedyna zmiana to wykorzystanie właściwości ItemTemplateSelector, która umożliwi nam korzystanie z więcej niż jednego szablonu.
    ListView

    Teraz przejdziemy do szablonu, po stronie widoku wygląda on tak …
    ItemTemplateSelector

    Klucz zapewnia nam dostęp do selektora, spójrz jeszcze raz w ListView, a na pewno sam zrozumiesz w jaki sposób przypisaliśmy selektor. Reszta atrybutów to atrybuty typu datatemplate, które musimy utworzyć samemu. Im przypisujemy rzeczywiste szablony tak jak robiliśmy to w kursie poprzednim. Zapewniam jednak, że to banalnie proste. Zanim przejdziemy do utworzenia selektora, przypomnę jeszcze jak korzystać datatemplate.

    DataTemplate dla PhotoItem

    PhotoListItem

    Teraz przejdziemy wreszcie do naszego selektora.

     public class ListViewSelector : DataTemplateSelector
        {
            #region DataTemplates
    
            public DataTemplate ImageTemplate { get; set; }
            public DataTemplate PhotoTemplate { get; set; }
    
            #endregion
    
            public override DataTemplate SelectTemplate(object item, DependencyObject container)
            {
                if (item is PhotoItem)
                    return PhotoTemplate;
                if (item is GalleryItem)
                    return ImageTemplate;
                return null;
            }
        }
    

    Nasz selektor dziedziczy po klasie DataTemlateSelector, znajdującej się w przestrzeni nazw System.Windows.Controls, czyli nie potrzebujemy w tym celu instalować żadnych dodatkowych narzędzi i bibliotek. Wystarczy, że utworzymy sobie dwa pola DataTemplate, którym jak już wcześniej widzieliśmy w widoku przypiszemy odpowiednie szablony. No i najważniejsza rzecz – nadpisanie metody SelectTemplate. W naszym przypadku rozpoznajemy tylko jakiego typu jest obiekt, równie dobrze można porównywać dane jednego typu np. pracowników, którzy w zależności od szczebla mają być inaczej wyświetlani.

    Moje rozwiązanie

    https://github.com/janczewskit/MVVM-Course-4-DataTemplateSelector

    Dodatek>

  • Jeśli selektor zwróci wartość null element zostanie wyświetlony, ale tylko w postaci nazwy klasy jakiej jest dany obiekt
  • Selektor pozwala na wybieranie z tylu typów szablonów ile tylko utworzymy i oczywiście obsłużymy.
  • Do czego mogą przydać się selektory? Zastosowań jest naprawdę wiele, od prostej listy czy drzewa pracowników, którzy różnią się w zależności od stanowiska aż po mapy na których możemy oznaczyć np. terytoria, pracowników czy siedziby.


    Tym krótki i mam nadzieję przyjemnym wpisem żegnam się z wami w tym roku i do zobaczenia w kolejnym ;)

  • Opublikowano Kurs MVVM | Otagowano , , , | Skomentuj

    Kurs MVVM #3 – Galeria obrazów (ObservableCollection, AncestorType i datatemplate)

    Wprowadzenie
    W tej części kursu dowiesz się jak stworzyć prostą galerię obrazów. Co to jest kolekcja ObservableCollection. Jak połączyć kolekcję elementów z kontrolką ListView. Do czego służy AncestorType i jak stworzyć szablon dla elementów na liście. Zaczynamy !

    Zadanie
    Utwórz aplikację WPF, a w niej jeden główny widok oraz połączony z nim viewmodel. W widoku umieść kontrolkę ListView i ustaw jej orientację na horyzontalną. Utwórz kolekcję obrazów i zbinduj z kontrolką ListView. Pod kontrolką umieść blok tekstu, który po kliknięciu w wybrany obraz wyświetli nam informacje o nim.

    Rozwiązanie
    Zaczynamy jak zwykle od widoku naszej aplikacji.
    Widok z podkreśleniami

    Na początku omówię to co znajduje się w kontrolce ListView. ItemsSource odpowiada za zbindowanie kolekcji elementów z kolekcją w viewmodelu. Tutaj należy zwrócić uwagę także na tryb bindowania (Mode = TwoWay) pozwala on na aktualizowanie interfejsu użytkownika (UI) wtedy, gdy zmieni się wartość obiektu z nim połączona i na zmianę danych jeśli zmienimy coś po stronie interfejsu użytkownika (Dzisiaj nie będziemy wykorzystywać tego w praktyce. Nauczymy się jak to robić w dalszych częściach kursu.). ItemTemplate zawiera szablon, który będzie obowiązywał dla każdego pojedynczego elementu naszej listy (to omówimy szerzej za chwilę). ItemsPanel zawiera szablon, który będzie obowiązywał dla kontrolki ListView. Bardziej jako ciekawostkę zastosowałem w swoim kodzie właściwość StringFormat przy bindowaniu TextBlocku. Pozwala ona tak samo jak jej odpowiednik w języku C# (String.Format()) na formatowanie tekstu. Szczególnie przydatna może okazać się przy formatowaniu daty i czasu.

    Teraz zajmiemy się szablonami dla naszego ListView.
    DataTemplate

    Na wstępie chciałem zaznaczyć, że Ja swój szablon utworzyłem w zasobach okna (Window.Resources), ale równie dobrze można zrobić to np. w zasobach grida (Grid.Resources) czy w innych miejscach poza naszym widokiem. Jednak wtedy musimy „poinformować” nasz widok o pliku, w którym znajduje się szablon . Jak już pewnie zauważyłeś szablony nie są bardzo skomplikowane. Wystarczy nadać mu klucz i możemy zacząć implementacje naszego szablonu. Elementy zbindowane w naszym szablonie ListItem są bindowane z poszczególnymi elementami na liście, czyli szablon traktujemy tak jakbyśmy bindowali go z jednym elemenetem, a nie listą. Szablon ListPanel zastosowany został do kotrolki ListView zmieniając w ten sposób jej orientację na horyzontalną (poziomą).

    Więcej uwagi poświęcimy znacznikowi InteractionTrigger (znajduje się on w szablonie ListItem zaraz po znaczniku grid). Triggery (pol. wyzwalacz) odpowiadają za wywoływanie zdarzeń. Aby skorzystać z Triggerów należy dodać do projektu referencję do biblioteki System.Windows.Interactivity (są także inne biblioteki do obsługi triggerów, Ja skorzystałem akurat z tej), a w widoku dodać następujący wiersz. xmlns:interactivity=”http://schemas.microsoft.com/expression/2010/interactivity”

    Wcześniej w buttonach, żeby obsłużyć zdarzenie przyciśnięcia wystarczyło nam użycie command (o czym pisałem więcej w pierwszej części kursu). Jednak nie zawsze jest tak łatwo. W tym konkretnym przypadku element Grid nie posiada właściwości Command, ale posiada za to zdarzenie MouseOnLeftButtonUp (liczba zdarzeń jest obszerna, inne zdarzenia można bindować analogicznie do tego). Nazwę zdarzenia przypisujemy do właściwości EventName, ale to jeszcze nie koniec. Musimy to zdarzenie jeszcze z czymś połączyć. W następnej linii widzimy, że możemy skorzystać z komendy – uff ! :) Jednak czy przypisywanie do każdego elementu komendy ma w tym przypadku sens? Trzeba, by utworzyć w naszym modelu dla każdego elementu komendę i pewnie powiadomić o niej jeszcze viewmodel np. jakimś delegatem czy akcją. Lepiej więc będzie jak utworzymy jedną komendę w naszym viewmodelu i przekażemy jej nasz element. Aby to zrobić skorzystamy z AncestorType. W ten sposób możemy połączyć się z viewmodelem, którego używa np. nasze okno (Window, mogą być inne typy jak np. grid). Właściwość CommandParameter przekaże nam w komendzie ten element, który klikniemy (Binding bez bez parametrów przekazuje cały zbindowany element).

    Przechodzimy do viewmodelu. Na początek utworzymy naszą kolekcję obrazów oraz model.
    Images
    GalleryItem
    W tym celu korzystamy z kolekcji ObservableCollection. Zaletą tej kolekcji sposób jej działania, który różni się od innych znanych nam „klasycznych” kolekcji. Spróbujmy rozszyfrować samą jej nazwę. Co oznacza observable ? Jeśli myślisz, że może mieć to coś wspólnego z wzorcem obserwator lub z programowaniem reaktywnym ( to masz rację. Zasada działania tego typu kolekcji jest stosunkowo prosta. O każdej zmianie w kolekcji informowani są wszyscy jej obserwatorzy. W naszym przypadku jest to widok. Jeśli np. usuniemy element naszej kolekcji to automatycznie zniknie on także z naszej galerii zdjęć.

    Aby nasza galeria nie była pusta w konstruktorze klasy utworzymy kilka przykładowych elementów (Dzisiaj zrobimy to jeszcze w ten sposób, dopiero w przyszłości zajmiemy się pobieraniem obrazów z bazy danych). Tworzenie kolekcji ObservableCollection i dodawanie elementów do niej robi się w analogiczny sposób co np. w kolekcji List.

    Jakie Ty dodasz obrazy do swojej kolekcji pozostawię już Twoim upodobaniom. Do pełni działania naszej aplikacji potrzebna nam jest jeszcze komenda do obsługi wybranego elementu. Komendy omawialiśmy już w poprzednim kursie, jednak dotychczas nie przekazywaliśmy wraz z nimi żadnych argumentów. Moja komenda wygląda tak.
    Komenda z argumentem

    Myślę, że ten kod nie wymaga specjalnego omawiania. Wspomnę tylko, że w nawiasach ostrokątnych podajemy typ danych, z którego skorzystamy w podpiętej do naszej komendy metodzie. Zaś zmienna SelectedItemName w moim przypadku została zbindowana z polem tekstowym, którego zadaniem jest wyświetlanie informacji na temat wybranego obrazu z galerii.

    Mam nadzieję, że udało Ci się stworzyć w pełni zgodny z założeniami projekt. Mimo tego, że wiele rzeczy w dzisiejszym kursie było nowych. Jeśli jednak napotkałeś pewne problemu. Tutaj link do mojego projektu.

    Polecam inne wpisy z tego kursu na naszym blogu! Oraz zapraszam do obserwowania fanpage’u Pasja-programowania

    Opublikowano Kurs MVVM | Otagowano , , , | 5 komentarzy

    Kurs MVVM #2 – Konwertery i style w widoku

    Wprowadzenie
    Jak dowiedzieliśmy się w pierwszym wpisie kursu istotą wzorca MVVM jest bindowanie. Czasem jednak chcielibyśmy wykorzystać już dostępne dane do zmian w naszym widoku czy ustawić widoczność pewnych elementów, ale zmienne w elemencie widoku mają inny typ niż te które posiadamy. Najpopularniejszy przykład to zmienne typu Visibility po stronie widoku i zmiennej typu bool, które chcielibyśmy do nich przypisać. Pisanie akcesorów do widoku typu Visibility i rzucanie ich wartości za każdym razem, gdy chcemy z nich skorzystać zaciemni kod i spowoduje najczęściej złamanie zasady DRY (ang. Don’t Repeat Yourself, pol. Nie powtarzaj się). Tutaj z pomocą przychodzą nam konwertery.

    Zadanie
    Utwórz aplikację WPF z jednym widokiem oraz dołączonym do niego viewmodelem. W aplikacji umieść następujące pola tekstowe (textboxy): login oraz hasło. Poniżej dodaj przycisk, który widoczny jest tylko wtedy, gdy oba pola nie są puste.

    Rozwiązanie
    Zaczynamy tradycyjnie od utworzenia widoku i viewmodelu oraz połączenia ich ze sobą (jeśli nie wiesz jak to zrobić zacznij od wpisu Kurs MVVM #1 – Wprowadzenie.
    Mój kod widoku wygląda tak …

    Widok z oznaczonym konwerterem i stylami

    Żółtym kolorem oznaczyłem 2 elementy. Najpierw zajmiemy się właściwością Visibility, bindujemy ją z IsVerifyTrue. Niby nic nadzwyczajnego, ale zaraz po tym występuje słowo Converter. Jak już pewnie się domyślasz (powinieneś jeśli przeczytałeś wstęp ;) ) nasza zmienna IsVerifyTrue jest innego typu niż Visibility i nastąpi konwersja typów. Zanim przejdziemy do typu tej zmiennej i tego jak wygląda nasz konwerter zatrzymamy się chwilkę nad pierwszym zaznaczeniem (mowa tu „Style ={StaticResource TextBoxStyle}”).

    W języku XAML możemy tworzyć i korzystać ze styli. Jest to szczególnie przydatne, gdy chcemy zapewnić naszej aplikacji jakiś motyw lub gdy w widoku powtarzają się pewne elementy o podobnych właściwościach przynajmniej kilka razy. Style możemy deklarować w plikach widoków lub też w odrębnych plikach słownikowych (Można utworzyć sobie taki plik przez „New Item”->”Resource Dictionary(WPF)”. Zachęcam do spróbowania również tego sposobu. Tutaj link jak się za to zabrać.

    Ja dzisiaj omówię jak to robić bezpośrednio w widoku. Wiemy już jak przypisać taki styl (Style=”{StaticResource NazwaStyle}”), ale nie wiemy jeszcze w jaki sposób można go utworzyć.A robi się to tak …
    XAML konwerter i style

    Na wstępie zaznaczę, że Windows.Resources jest bezpośrednim potomkiem znacznika Windows. Omawianie zaczniemy od niebieskiej klamry. Myślę, że nazwa znacznika Style oraz znaczniki Setter są łatwe do rozszyfrowania. TargetType odpowiada za typ do jakiego odnosi się nasz styl zaś x:Key to klucz dzięki, któremu możemy użyć naszego stylu w wybranym elemencie widoku.

    Czym jest zatem żółte podkreślenie ? Dzięki tej właśnie linii możemy użyć konwertera w widoku.
    Nazwa od której zaczyna się znacznik („converters”) zawiera ścieżkę do folderu, w którym znajduje się konwerter.
    W moim przypadku jest to …
    Ścieżka do konwertera

    Mój konwerter nazwałem MainWindowViewModelToVisibleConverter. Za co odpowiedzialny jest atrybut x:key powinieneś już wiedzieć.

    Konwerter po stronie widoku mamy już omówiony. Został nam jeszcze viewmodel. Zaczynamy od deklaracji akcesora odpowiadającej temu co mamy w widoku. Ja zrobiłem to w ten sposób …
    Prop przekazywany w konwerterze

    Czemu akurat jako typ podałem viewmodel? Z dwóch powodów. Pierwszy – dlatego, że w zadaniu poproszono nas o sprawdzenie czy pola login oraz hasło nie są puste, a będzie to można sprawdzić mając dostęp zbindowanych pól z naszym viewmodelem. Drugi jest taki, że nasza zmienna zostanie przekazana do konwertera (czyli w praktyce bindować możemy niemal dowolne zmienne).

    Brakuje nam jeszcze jednej rzeczy! Oczywiście mowa tu o konwerterze. Konwerter to nic innego jak klasa, która posiada dwie metody, odpowiadające za konwersję jednego typu do drugiego (nie mylić z rzutowaniem, chociaż też taki przypadek konwersji może się oczywiście zdarzyć). Metody te zapewnia nam interfejs IValueConverter. Wystarczy je odpowiednio ukonkretnić. Ja ponadto zawsze tworzę folder na konwertery o nazwie Converters. Zobaczmy jak to wygląda w praktyce.
    Konwerter

    Zmienna value jest oczywiście zmienną typu, który zadeklarowaliśmy w viewmodelu (najczęściej w przypadku visibility będzie to jednak zmienna bool). W metodzie konwersji dążymy oczywiście do zwrócenia wyniku w typie zgodnym z XAML.

    Robimy test naszej aplikacji i okazuje się, że …. ? Przycisk się nie wyświetla mimo wypełnionych pól!
    Zapomnieliśmy o czymś! Akcja przypisana do widoczności przycisku w ogóle się nie uruchamia. Ale zaraz przecież my jej wcale nie używamy! Trzeba ją jakoś wywołać! Najprościej chyba będzie tak …
    Prop loginu z wywołaniem prop IsVerifyTrue

    Eureka! Jeśli przy zmianie w polu loginu lub hasła nastąpi zmiana to wywołamy sprawdzenie naszego założenia o widoczności przycisku. W konwerterze zostaną sprawdzone odpowiednie właściwości viewmodelu i otrzymamy żądany rezultat. Koniec ;)

    Jeśli masz jakieś problemy z powyższym zadaniem. Możesz skorzystać z mojego rozwiązania.
    Link do projektu.

    Ciekawostki

  • Jeśli w danym widoku zdefiniujemy sobie styl np. dla kontrolki Textbox i nie nadamy mu klucza (wartości x:Key) to zostanie on przypisany do wszystkich Textboxów w widoku, które nie mają przypisanego stylu.

  • Aplikacja WPF zapewnia nam pewną liczbę gotowych konwerterów. Jednym z nich jest „BooleanToVisibilityConverter” zmieniający wartość typu boolowskiego w viewmodelu na wartość Visibility w widoku. Aby skorzystać z gotowego konwertera wystarczy dodać go bez żadnego przedrostka w „resourcach” widoku.
  • Opublikowano Kurs MVVM | Skomentuj

    Kurs MVVM #1 – Wprowadzenie

    MVVMPattern
    Schemat wzorca MVVM

    Przedmowa
    Co to właściwie takiego jest MVVM ? Na czym polega bindowanie i jakie są jego rodzaje ? Jak walidować przy pomocy MVVM ? Co to logika biznesowa ? Na wszystkie te pytania oraz wiele innych, które pojawią się w trakcie trwania tego kursu postaram się odpowiedzieć i pokazać jak się za nie zabrać w formie prostych przykładów.

    Jak mówił klasyk „czasem człowiek musi, bo inaczej się udusi” – czyli będzie trochę prywaty. Kurs ten powstał z jednego bardzo ważnego powodu ! Brak (dobrej) literatury
    i jakichkolwiek kursów w tym temacie. Po prostu tragedia ! Omówione jedynie podstawy albo zupełnie tematy z innej beczki pod przykrywką nazwy z MVVM w tytule :) Jednak, żeby nie wyszło, że to tylko ból tyłka postanowiłem wziąć się do działania. Dzisiaj tylko krótkie wprowadzenie, zapraszam! ;)

    Wprowadzenie
    MVVM to wzorzec architektoniczny stosowany m.in. w technologiach Silverlight czy WPF. W języku polskim czytamy jako model-widok-widok model (ang. Model-View-ViewModel). Podobnie jak ostatnio bardzo popularny wzorzec MVC składa się on z 3 warstw.
    M – Model
    V – View (inaczej widok)
    VM – ViewModel

    Widok jest to graficzna część aplikacji. ViewModel zastępuje nam code-behind znany z takich technologii jak WinForms czy Asp.net Web Forms. Inaczej można powiedzieć, że viewmodel odpowiada za obsługę wszystkich akcji, które połączone są z widokiem. Model odpowiada zaś za logikę aplikacji. W kolejnych wpisach dowiemy się również, że m.in. tego, że pomiędzy modelem, a viewmodelem istnieje jeszcze warstwa logiki biznesowej, jednak teraz nie zaprzątajmy sobie tym głowy.

    Zadanie
    Utwórz aplikację w technologii WPF. W niej znaleźć ma się jeden widok oraz połączony z nim viewmodel. Widok ma zawierać 2 bloki tekstowe ( jeden na imię, drugi na nazwisko użytkownika) oraz przycisk. Oba pola tekstowe mają mieć wpisany tekst domyślny widoczny tak, by nigdy te pola nie były puste (przy uruchomieniu programu oraz jeśli użytkownik usunie cały tekst z pola). Kliknięcie w przycisk ma spowodować sprawdzenie czy pola zostały wypełnione przez użytkownika.

    Rozwiązanie
    Tworzymy projekt w Visual Studio typu WPF Application. W pliku MainWindow.xaml projektujemy widok naszego zadania zgodnie z wytycznymi. Np.

    widok bez połączenia z viewmodelem
    Następnie tworzymy klasę viewmodelu. Ja utworzyłem folder o nazwie viewmodels i w niej utworzyłem klasę o nazwie MainWindowViewModel. Aby ułatwić sobie pracę zgodnie z wzorcem MVVM do projektu doinstalowałem framework PRISM (istnieje wiele różnych frameworków wspomagających MVVM, można wybrać oczywiści inny). Tutaj link do paczki nuget.
    Aby nasza klasa nie była tylko klasą, a viewmodelem musimy ona dziedziczyć po klasie lub interfejsie pozwalających na komunikację z widokiem. Ja w moim rozwiązaniu korzystam z BindingBase.

    klasa viewmodelu
    Teraz musimy jakoś połączyć nasz widok z viewmodelem. Możemy to robić zarówno w code-behind widoku jaki w samym XAMLu. Ja w tym celu użyłem XAMLa, a code-behind zostawię sobie bez zmian. Najpierw trzeba zadeklarować w tym celu ścieżkę do viewmodelu, a później ustawić go jako DataContext. U mnie wygląda to tak …
    Łączenie z viewmodelem w widoku

    Żółtym kolorem została oznaczona ścieżka.
    Kod objęty klamrą łączy nasz widok z viewmodelem.

    Teraz skupimy się na najważniejszej rzeczy, którą dzisiaj chcę przedstawić.
    Jeśli dokładnie przeanalizowałeś/aś nasz kod zawierający widok mogłeś zauważyć, że w kilku miejscach znajduje się słowo binding. Słowo to jest odpowiedzialne za magię łączenia (bindowania) wartości w widoku ze zmiennymi w viewmodelu. Wróćmy jeszcze na chwilę do tego kodu …

    widok z oznaczonymi bindowaniami

    Widzimy, że elementy, które chcemy połączyć z viewmodelem nadajemy nazwy. Mamy kilka opcji bindowania oznaczonych jako mode, opcje te można samemu rozszyfrować po nazwach, zostaną one też omówione w jednym z kolejnych wpisów. Przy atrybucie tekst mamy także coś takiego co nazywa się UpdateSourceTrigger. O triggerach (wyzwalaczach) opowiem kiedyś indziej, dziś należy wiedzieć, że ustawienie tej zmiennej na propertychanged spowoduje, że przy zmianie tej wartości w viewmodelu zmieni ona się także w widoku (i w odwrotną stronę też).

    Przejdźmy teraz do widoku. Tutaj musimy „obsłużyć” to czym chcemy zarządzać. Zaczniemy od wartości tekstowych.

    Bindowanie po stronie viewmodelu

    Na powyższym obrazie Ja już napisałem logikę dla pola Name. Najważniejsze jest pole to było publicznym akcesorem (ja zwykle używam propfull i tego radziłbym się trzymać ;) no i oczywiście nazwa musi zgadzać się z tą użytą w widoku.

    Została nam jeszcze jedna rzecz. Bindowanie komend. Do tego celu używamy akcesora typu ICommand. Zobaczmy jak to wygląda w praktyce.

    Bindowanie komendy

    Myślę, że to by było na tyle. Oczywiście, żeby Twój program w pełni działał trzeba go dokończyć. Jeśli jednak nie radziłbyś sobie możesz skorzystać z mojego projektu Link do projektu. Powodzenia !

    Opublikowano Bez kategorii, Kurs MVVM | Otagowano , , , , | 7 komentarzy