• This is a usual time of the year for summaries so let’s keep the tradition alive and write one. Here’s my 2017 achievements split between months. January Blogging for 18 days straight – nothing near gutek’s achievement (whole year!) but still a nice streak Microsoft MVP title (thx Konrad Kokosa for pointing this one ;)) February […]

  • “Advent of Code is a series of small programming puzzles for a variety of skill levels.” Each day was a fun an interesting coding challenge. I’ve decided to practice and code this in python to learn the skill. Some of them might not be the best python scripting as I was short on time in […]

  • Some time ago I’ve attended a .net developer days 2017 conference. I was quite busy since (traveling, teaching .net, working) that only now I got some time to share some thoughts about it. As a bonus I’m including a short interview I did during the event. I need to state here, just to be clear, […]

  • We developers don’t like documentation. We don’t like to read it, and we even more we don’t like to write it. But sometimes it is worth to read it. Like when you find out that by using datetime in SQL DB you got a milliseconds precision but only if it ends on 0,3,7 (link). That […]

  • In the previous post we’ve removed some of the technical debt that could be found in our NetDeveloperPoland Website application. In this one we will remove it even more. We can even maybe reach a B? Let’s see where we’ll end up at the end of this part.

Po dłuższej przerwie wracamy do kursu o WPF. Dziś będzie o stylach.

WPF wprowadza nowość w zakresie zmiany wyglądu kontrolek. Wszystkie są stworzone w taki sposób, że logika jest oddzielona od wyglądu. Dzięki temu możemy zmienić wygląd cały czas zachowując funkcjonalność.

Style

Co za pomocą nich możemy uzyskać?
Załóżmy, że chcemy zmienić wygląd przycisków w naszej aplikacji, moglibyśmy zmieniać te same ustawienia dla każdego przycisku oddzielnie, ale za pomocą stylów możemy to zrobić w jednym miejscu i po prostu przypisać nasze ustawienia do każdego przycisku. Zobaczmy na krótki przykład:

<StackPanel.Resources>

    <Style x:Key=”przycisk”>

        <Setter Property=”Button.FontSize” Value=”22″ />

        <Setter Property=”Button.Background” Value=”Orange” />

        <Setter Property=”Button.Width” Value=”60″ />

    Style>

StackPanel.Resources>

Definiujemy sobie, iż nasze przyciski będą na 60 pixeli szeroie,, tło będzie ustawione na kolor pomarańczowy oraz rozmiar fontu ustawimy na 22.
Jak użyć takich ustawień? Zaaplikujemy je do właściwości Style.

<Button Content=”1″ Style=”{StaticResource przycisk}”/>

<Button Content=”2″ Style=”{StaticResource przycisk}”/>

<Button Content=”3″ Style=”{StaticResource przycisk}”/>

<Button Content=”4″ Style=”{StaticResource przycisk}”/>

<Button Content=”5″ Style=”{StaticResource przycisk}”/>

Jaki da nam to efekt?

Oczywiście możemy też ustawiać bardziej skomplikowane właściwości

<Setter Property=”Button.RenderTransform”>

    <Setter.Value>

        <SkewTransform CenterX=”.5″ CenterY=”.5″ AngleX=”-10″ AngleY=”15″ />

    Setter.Value>

Setter>

Dodatkowo jeśli chcemy możemy ograniczyć dany styl, tylko no konkretnej klasy. Jeśli nasz styl zapiszemy jako:

<Style TargetType=”{x:Type Button}”>

    <Setter Property=”FontSize” Value=”22″ />

    <Setter Property=”Background” Value=”Orange” />

    <Setter Property=”Width” Value=”60″ />

    <Setter Property=”RenderTransform”>

        <Setter.Value>

            <SkewTransform CenterX=”.5″ CenterY=”.5″ AngleX=”-10″ AngleY=”15″ />

        Setter.Value>

    Setter>

Style>

Wtedy wszystkie przyciski automatycznie przyjmą ten styl. Oczywiście nadal będziemy mogli zmienić wygląd przycisku na poziomie konkretnego obiektu.

O stylach na dziś tyle. Następnym razem będzie o triggerach.

Taki właśnie jak powyżej (oczywiście bez blura), wyglądał komunikat błędu, gdy wpisałem niepoprawny login i hasło w jednym z serwisów. Zastanawiam się czy programista piszący ten serwis ma jakiekolwiek pojęcie co robi i czy wie jak ułatwia sprawę komuś, kto chciałby te informacje wykorzystać. Czasem wydaje mi się, że bezpieczeństwo to temat, któremu nie poświęca się dużo czasu bo i po co. Ja w swoich programach dbam o to, aby bezpieczeństwo było tak samo ważnym elementem jak działająca funkcjonalność.

A jak bezpieczeństwo wygląda w waszych aplikacjach? Czy jest uwzględniane już od początku projektu czy raczej coś co zostawia się na koniec do zaimplementowania przez studenta podczas praktyk wakacyjnych? (z całym szacunkiem dla tych ostatnich).

Dostępność równoległej pętli For była już dostępna w CTP. Jednak ze względu, iż była to wirtualna maszyna użycie jej było bardzo ograniczone (bez wirtualizacji VPC ma jeden wątek). Skoro teraz jest już Beta postanowiłem się temu przyjrzeć ponownie.

Parallel

Nowy Framework daje nam do dyspozycji trzy warianty: For,For<> oraz ForEach<>. Użycie? Proste:

Parallel.For(1, 10000, delegate(int i)

                          {

                          });

Warto zwrócić uwagę, że jest to przedział lewostronnie domknięty lub ParallelOptions, za pomocą którego możemy ustawić kilka opcji naszego równoległego wykonania.

Wraz z nowym obiektem dostajemy także wsparcie w Visual Studio 2010. Pierwszym z nich to okno Parallel Tasks. Pozwala podejrzeć aktualnie nasze aktualnie uruchomione wątki jak i dokonać kilku operacji na nich (zatrzymanie, wznowienie).

Drugie to ParallelStack – to okno pokaże nam stos wywołań naszych wątków. Zacne. Jak to wygląda na obrazku poniżej.

Zachęcam do zabawy z Parallel. Nie masz pomysłów na algorytm wykorzystujący te możliwości? “Kilka” takich zadań, znajdziesz na ProjectEuler.Net. Problemy matematyczne do rozwiązywania za pomocą komputera (lub głowy – da się da…:)).

Wszystkich fanów matematyki i ciekawych problemów zachęcam do zajrzenia tam no i do zaznajomienia się z nową równoległą pętlą w VS 2010.

Czasami podczas wprowadzania danych zachodzi potrzeba ich walidacji (a w zasadzie zawsze jest). W tym odcinku zobaczymy jak możemy takie reguły walidacyjne do naszego interface’u. Możemy to zrobić na dwa sposoby. Pierwszy z nich to napisanie własnej metody walidacji, drugi to przekazanie wszystkich wystąpionych wyjątków jako elementów systemu walidacji. Zobaczmy to na przykładach. Aby napisać nową klasę walidacji jedyne co musimy zrobić to napisać nową klasę, która dziedziczy po klasie ValidationRule. Najprostsza klasa ma postać:

public class AlwaysFailingValidationRule : ValidationRule

{

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)

    {

        return new ValidationResult(false, “Always failing”);

    }

}

Ta prosta reguła zawsze będzie zwracać fałsz przy walidacji danych. Jak tego użyć w XAMLu?

<TextBox x:Name=”f” />

<TextBox x:Name=”fileName”>

    <TextBox.Text>

        <Binding Path=”Text” ElementName=”f” Mode=”TwoWay”>

            <Binding.ValidationRules>

                <local:AlwaysFailingValidationRule />

            Binding.ValidationRules>

        Binding>

    TextBox.Text>           

TextBox>

Metoda ta jest wywoływana jeszcze przed przekazaniem danej do ewentualnego konwertera. Jeśli chcemy “upiększyć” wygląd kontrolki w przypadku błędu, możemy to zrobić definiując wygląd tego stanu w elemencie Validation.ErrorTemplate.

Wyjątki

Możemy też skorzystać w dostarczanego wraz z WPF elementu

<ExceptionValidationRule />

W takim przypadku wysztkie wyjątki jakie się pojawią będą traktowane jako złamanie reguł walidacji.

Klasa Binding

Jeśli tworzymy binding z kodu, możemy posłużyć się właściwością UpdateSourceExceptionFilter i w nim wpiąć trochę kodu, odpowiedzialnego za logikę.

Następnym razem będzie o stylach w WPF.

Byłeś/byłaś na C2C’09? Podobała ci się konferencja i popierasz ideę za nią stojącą?

Wspomóż C2C!

Oficjalna notka organizatorów poniżej:

Przygotowania do konferencji C2C 2009 rozpoczęły się w październiku 2008 roku. Od strony finansowej całe przedsięwzięcie obsługiwać miało stowarzyszenie PDG, które rozliczało również C2C 2008. Na początku 2009 roku PDG zrezygnowało ze współpracy z grupami off-line. Dla organizatorów C2C 2009 oznaczało to brak możliwości rozliczenia konferencji C2C. Na szczęście dzięki uprzejmości fundacji PROIDEA stan taki nie trwał długo. Konferencja szczęśliwie została zorganizowana. Niestety stowarzyszenie PDG do dnia dzisiejszego nie przelało wszystkich środków C2C na konto PROIDEI. Z tego powodu budżet konferencji posiada niedobór środków na kwotę ponad 6 000 PLN. Dlatego też zwracamy się do wszystkich osób, którym idea konferencji jest blisko o pomoc.

Każda kwota się liczy. Z góry dzięki. Ja już swoją cząstkę przelałem.

Edit: Żeby nie było, że wyciągam kasę to ta sama notka na stronie głównej konferencji.

Zainteresowałem się ostatnio nowym (a może już nie nowym) notebookiem od Dell’a a mianowicie – Mini 10v. Stwierdziłem, że przyjrzę się mu bliżej tak więc zabrałem się za konfigurację maszynki. W pewnym momencie przyszło do konfigurowania systemu operacyjnego. Trochę się zdziwiłem widzą taką możliwość wyboru jak poniżej:

Innych opcji do wyboru nie ma. Wygląda zatem na to, że MS wchodzi z nowym systemem operacyjnym :). Micorosft XP SP 3 jest dostępny w innych wersjach notebooka, ale chyba powinni zastąpić ten tekst “System operacyjny firmy Microsoft” po prostu na “System operacyjny” :).

W poprzednim odcinku omówiony (pobieżnie) został mechanizm DataBindingu. Dziś powiemy sobie co robić, abyśmy mogli w trochę większym stopniu niż dotychczas kontrolować to w jaki sposób wyświetlamy nasze dane.

ValueConverters

Załóżmy, że na potrzeby tego wpisu mamy prostą klasę:

public class Device

{

    public bool Active { get; set; }

}

Oczywiście chcemy jej właściwość Active wyświetlić na UI i oczywiście posługujemy się bindingiem.

<CheckBox Content=”Active?” IsChecked=”{Binding Active}” /> 

(źródło danych ustawiamy za pomocą DataContext). Co jednak, gdy wartości tej nie chcemy wyświetlić za pomocą klasy CheckBox a np. obrazka? Z pomocą przychodzi nam ValueConverter. Oczywiście nie będziemy zmieniać naszej zaawansowanej logiki, aby zwracała obrazek. Napiszemy odpowiednią klasę.

public class BoolToImageConverter : IValueConverter

{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    {

        if (targetType != typeof(ImageSource))

            throw new InvalidOperationException(“The target must be a ImageSource”);

 

        return (bool) value

                  ? new BitmapImage(new Uri(“Yes.png”, UriKind.Relative))

                  : new BitmapImage(new Uri(“No.png”, UriKind.Relative));

    }

 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    {

        throw new NotSupportedException();

    }

}

Nasza klasa konwertera jest niezwykle prosta. Implementujemy interface IValueConverter i tworzymy implementację metod Convert oraz ConvertBack. W naszym przypadku udostępniamy tylko konwersją w jedną stronę. Na podstawie wartości parametru zwracamy odpowiedni obrazek. Dodatkowo nasz metoda mogłaby brać pod uwagę aktualną kulturę i wyświetlać obrazek w zależności od tej. Jak tego użyć?
Deklarujemy nasz konwerter:

<Window.Resources>

    <local:BoolToImageConverter x:Key=”BoolToImageConverter” />

Window.Resources>

A następnie używamy przy bindingu

<Image Source=”{Binding Path=Active, Converter={StaticResource BoolToImageConverter}}” Width=”20″ Height=”20″/>

Efekt końcowy?

Ładniutki plusik 🙂

Templatki

Wiele z kontrolek udostępnia możliwość zdefiniowana wyglądu danych, które prezentują. Robi się to za pomocą definiowania nowego wyglądu w tagu DataTemplate. Zobaczmy jak to działa na przykładzie klasy ListBox. Stwórzmy sobie klasę do przechowywania zdjęć wraz z ich nazwą:

public class File

{

    public string Name { get; set; }

    public string Path { get; set; }

}

oraz wypełnijmy ją jakimiś danymi

const string path = @”C:\Users\pawlos\Pictures\Sample Images\Nature”;

var files = from file in Directory.GetFiles(path, “*.jpg”)

            select new File() {Name = Path.GetFileName(file), Path = file};

a nasz ListBox zdefiniujemy następująco

<ListBox x:Name=”listbox”>

    <ListBox.ItemTemplate>

        <DataTemplate>

            <StackPanel>

                <Label Content=”{Binding Name}” />

                <Image Source=”{Binding Path}” Height=”50″ />

            StackPanel>

        DataTemplate>

    ListBox.ItemTemplate>

ListBox>

W efekcie dostaniemy ładnie wyświetlone zdjęcia wraz z nazwą odpowiadającego pliku

Na dziś tyle. Następnym razem będzie o walidacji podczas bindowania.

Dzisiejszy odcinek poświęcony będzie zagadnieniu DataBindning. Zagadnienie to nie jest nowe – mamy je także w Win i WebForms, jednak w przypadku technologii WPF nabiera ono zupełnie nowego wymiaru.

Binding w kodzie

Możemy to zrobić w prosty sposób za pomocą elementy Binding

Binding binding = new Binding();

binding.Source = tekst;

binding.Path = new PropertyPath(“Text”);

label.SetBinding(TextBlock.TextProperty, binding);

Dzięki takiemu zabiegowi tekst, tekst który wprowadzimy pojawi się także w polu label. Binding taki będzie aktywny, aż do czasu, aż go nie wyczyścimy:

BindingOperations.ClearBinding(label, TextBlock.TextProperty);

To samo można osiągnąć, poprzez jawne podstawienia wartości pod docelową właściwość (w tym przypadku Text.

XAML

Podobny zabieg bindowania możemy oczywiście zdefiniować w języku XAML.

<TextBox x:Name=”tekst” />

<TextBlock x:Name=”label” Text=”{Binding ElementName=tekst, Path=Text}” />

Warto zauważyć, iż posługujemy się właściwością ElementName. Możemy oczywiście użyć Source, ale wtedy nasz element musielibyśmy zdefiniować w słowniku ResourceDictionary i odwoływać się do niego za pomocą StaticResource.

Bindowanie do prostych właściwości w .NET

Jeśli chcemy umożliwić binding w naszych klasach musimy odpowiednio je przygotować. Mamy do wyboru dwa podejścia (preferowane pierwsze):

  • implementujemy w naszej klasie interface INotifyPropertyChanged, który zawiera jeden wspólny event PropertyChanged

  • implementujemy eventy XXXChanged dla każdej z właściwości, którą chcemy móc bindować

Dodatkowo jeśli nasza klasa jest kolekcją i chcemy do niej bindować warto skorzystać z klasy ObservableCollection, która już ma zaimplementowane notyfikacje dla operacji na niej (Add, Remove, Clear). Bindowanie to obiektów, które nie dziedziczą po klasie UIElement spowoduje, że w wyniku dostaniemy zwrócony tekst z wykonania metody ToString().

Bindowanie kolekcji

Bindując kolekcję zapewne posłużymy się, jedną z kontrolek umożliwiająca wyświetlenie kolekcji elementów – np. ListBox. W przypadku tej kontrolki element źródłowy podpinamy do właściwości ItemsSource. Jeśli chcemy wyświetlać element inny niż wynik wykonania metody ToString powinniśmy ustawić właściwość DisplayMemberPath. Jeśli chcemy współdzielić dany obiekt źródłowy bindowania przez wiele kontrolek powinniśmy ustawić go jako wartość właściwości DataContext a na poszczególnych kontrolkach bindować do poszczególnych właściwości.

Następnym razem będzie trochę o kontrolowaniu tego jak wyglądają nasze zbindowane elementy – ValueConverter, DataTemplate.

Wszyscy zabierają się za testowanie najnowszej wersji Visual Studio 2010 Beta 1, tak więc postanowiłem i ja się przyjrzeć co tam jeszcze ciekawego na nas czeka. Na pierwszy ogień poszła funkcjonalność debuggera.

VS 2010 umożliwia nam eksport i import zdefiniowanych e naszej aplikacji breakpointów.

Breakpointy zapisywane są w pliku XML, tak więc można je edytować ręcznie w pliku. Oczywiście breakpointy są zapamiętywane jako ustawione w danej linii tak więc gdy dodamy dodatkowe linie “psując” stary porządek linii, breakpointy gubią się (ale to raczej oczywiste). Dodatkowo breakpointom możemy nadawać etykiety.

Zastanawiam się nad potrzebą takich funkcjonalności. Jedyne jakie widzę (grubo naciągane) to szybkie przekazanie ustawienia skomplikowanych breakpointów w przypadku debuggowania skomplikowanego problemu. Jednak być może funkcjonalność ta wykorzystywana jest w przypadku “historycznego debuggera

Dziś będzie poruszony temat zasobów w WPF. A mówiąc ściślej zasobów binarnych. Zasoby te mogą być umieszczone w 3 różnych miejscach. Mogą być:

  • wewnątrz assembly

  • “luźne” pliki znane aplikacji w czasie kompilacji

  • “luźne” pliki nieznane aplikacji podczas kompilacji

Gdy dodajemy nowy zasób do wyboru mamy mnóstwo opcji:

Dla nas istotne są:

  • Resource – umieszcza zasób w assembly

  • Content – pozostawia zasób jako “luźny” plik, ale odnotowuje fakt jego istnienia poprzez dodanie odpowiedniego atrybutu (AssemblyAssociateContentFile)

Lista duża, ale warto zwrócić uwagę na to czego nie stosować. Embedded Resource – jest to sposób znany sprzed WPF i powinien być unikany w aplikacjach.
Zanim przejdziemy do omówienia jak dostawać się do zasobów, mała uwaga. Jeśli chcemy aby nasze zasoby były lokalizowalne, należy umieszczać je jako Resource

Dostęp do zasobów

Aby użyć zasobów zdefiniowanych jako Resource wystarczy napisać:

<Image Source=”conan_doyle.gif” />

Prawdziwy problem z zasobami w WPF jest z rozszyfrowaniem ścieżki URI. Ta, bowiem może przyjmować wiele form. Spróbujmy pokrótce je omówić:

  • A/B/plik.jpg – zasób znajduje się w danym assembly, lub jest to “luźny” plik. A/B/ definiują strukturę podkatalogów (jeśli występują).

  • c:\folder\plik.jpg lub file://c:/folder/plik.jpg – “luźny” plik w folderze c:\folder

  • PlikDll;Component/A/B/plik.jpg – zasób zawarty w innym assembly (.dll lub .exe) znajdujący się w ewentualnym podkatalogu A/B/

  • pack://siteOfOrigin:,,,/A/B/plik.jpg – “luźny” plik znajdujący się w katalogu aplikacji (lub w podkatalogu A/B/ jeśli zdefiniowane)

Lokalizowanie zasobów

Lokalizowanie WPF’a to troszkę uciążliwy proces. Składa się wygenerowaniu unikalnych identyfikatorów dla każdego elementu naszego pliku XAML (można ro zrobić za pomocą narzędzia msbuild – msbuild.exe /t:updateuid NazwaProjektu.csproj). Następnie za pomocą narzędzia LocBaml generujemy plik .csv, w którym będziemy mogli przetłumaczyć na dowolny język. Dokładny opis można znaleźć w tym artykule.

Następnym razem będzie temat DataBindingu (co prawda na liście w kolejności jest temat obrazków – ale nie wiem co jeszcze w tym temacie można napisać).