piątek, 30 listopada 2012

EF połączenie do MySql - nieobsługiwane słowa klucozwe

Problem:
Podczas próby pobrania danych przez EF z bazy MySql otrzymuje błąd:






Treść błędu: Keyword not supported: 'port'.

Tak więc problem z nieobsługiwanym elementem Connection String. Jeżeli baza stoi na domyślnym porcie dla niej przeznaczonym, nie ma problemu. Można je bezpiecznie usunąć.
Sprawa się komplikuje jeżeli baza nie stoi na domyślnym porcie, lub też nie możemy go zmienić.

Rozwiązanie:

Aby poradzić sobie z tym problemem, możemy go obejść i dać kontekstowi gotowe połączenie do bazy. Dodajemy konstruktor do naszego kontekstu:

Code:
public DatabaseContext(DbConnection connections, bool contextOwnsConnection)
            : base(connections, contextOwnsConnection)
        {
            
        }

Pierwszy parametr to nasze połączenie, drugi mówi o tym czy połączenie będzie zarządzane przez kontekst. Jeżeli przekażemy wartość true, połączenie zostanie zwolnione podczas zwalniania kontekstu. Jeżeli nie zgodzimy się na zarządzanie połączeniem przez kontekst musimy pamiętać o tym, aby zwolnić je samemu.

Samo stworzenie kontekstu i przekazanie do niego połączenia jest jest rzeczą trywialną:

Code:
            string connectionString = "Server = localhost; Port = 3307; Database = mojabaza; Uid = uzytkownik; Pwd = haslo; Charset=latin1;";
            var mySqlConnection = new MySqlConnection(connectionString);
            using (var context = new DatabaseContext(mySqlConnection, true))
            {
                var projects = context.Tabela.ToList();
            }

czwartek, 29 listopada 2012

Domain Driven Design

Domain Driven Design (DDD) zostało zdefiniowane przez Erica Evansa w jego książce Domain-Driven Design: Tackling Complexity in the Heart of Software wydanej w 2003 roku.
DDD nie jest metodyką tworzenia kodu, a definiowaniem komunikacji (połączeń) pomiędzy obiektami.
DDD mówi o tym w jaki sposób rozmawiać z klientem, abyśmy mogli zrozumieć domenę problemu - czyli sedno tego, co następnie opakujemy w kod.
Eric stworzył wiele koncepcji. Niektóre z nich:
  • Model-Driven design
  • Bounded Contex
  • Core Domain
  • Generic Subdomains
  • Context Map

Szczególnie ciekawa koncepcja to Bounded Context - wyrażenie to przetłumaczył bym jako ograniczony czy też zawężony kontekst.
W większości projektów, tworzony jest jeden model, który reprezentuje całą aplikację. Bounded Context ma za zadanie podzielić problem na mniejsze, czyli stworzyć wiele małych modeli. Każdy z małych modeli dotyczy jednego specyficznego obszaru i definiuje operacje tylko z nim związane. Jako deweloperom daje nam to wskazówki, co w danym modelu ma zostać zaimplementowane, a co powinniśmy przenieść do innego/nowego modelu.

Standardowo tworzoną aplikację można przedstawić w następujący sposób:


Jeżeli chcielibyśmy tutaj wykorzystać metodykę Bounded Context, podział mógłby wyglądać następująco:


Encja Customer występuje w wielu kontekstach. Nie jest więc twardo powiedziane, że dana encja ma się w całym modelu pojawić tylko raz. Oczywiście nie znaczy to, że w każdym miejscu musi posiadać ten sam zbiór pól i operacji. W kolejnym poście pojawi się przykład obrazujący tworzenie Bounded Context. 

środa, 28 listopada 2012

O czym pamiętać przy zmianie stanu encji w EF

Manipulując stanem encji, należy pamiętać o dwóch zasadach. Dotyczą one zapisu zmian do bazy danych po zakończeniu pracy z obiektami i ustawianiu im stanów.

W przypadku użycia metod:
  • Add
  • DbContext.Entry(obj).State = EntityState.Added
jeżeli obiekt zawiera referencje do innych obiektów, zostaną one także dołączone do kontekstu i przy wywołaniu metody SaveChanges() zapisane do bazy. Przykład:

Code:
            using (var context = new AdventureWorksLTEntities())
            {
                var customer = new Customer { FirstName = "Jacek", LastName = "Kowalski" };
                customer.CustomerAddresses.Add(new CustomerAddress 
                { Address = new Address { AddressLine1 = "Ulica Polkowa", PostalCode = "45-123" } });
                context.Entry(customer).State = System.Data.EntityState.Added;
                context.SaveChanges();
            }

zarówno obiekt klasy Customer, jak i CustomerAddresses oraz Address zostaną zapisane do bazy.

Przeciwieństwem powyższego zachowania jest przyczepienie obiektu, który istnieje już w bazie danych do kontekstu, czyli użycie metody:
  • Attach
  •  DbContext.Entry(obj).State = EntityState.Unchanged
  •  DbContext.Entry(obj).State = EntityState.Modified

Code:
            var customer = GetCustomerFromRepository();
            using (var context = new AdventureWorksLTEntities())
            {
                customer.CustomerAddresses.Add(new CustomerAddress 
                { Address = new Address { AddressLine1 = "Ulica Polkowa", PostalCode = "45-123" } });
                context.Entry(customer).State = System.Data.EntityState.Unchanged;
                context.SaveChanges();
            }

Powyższy przypadek nie spowoduje dodania nowych obiektów klas CustomerAddresses oraz Address do bazy danych.

Entity Framework - Graph Object State

Encja pobrana z bazy za pomocą EntityFramework może mieć jeden z następujących stanów:
  • Added - encja jest śledzona przez kontekst, ale nie istnieje w bazie danych
  • Unchanged - encja jest śledzona przez kontekst oraz istnieje w bazie danych. Wartości pól są takie same w bazie jak i obiekcie (nie dokonano żadnych zmian).
  • Modified - encja jest śledzona przez kontekst, istnieje w bazie danych. Dokonano zmian w jej polach
  • Deleted - encja jest śledzona przez kontekst i istnieje w bazie danych. Została jednak oznaczona do usunięcia. Przy następnym wywołaniu SaveChanges zostanie usunięta z bazy danych
  • Detached - encja nie jest śledzona przez kontekst

Standardowe operacje w przypadku Encji w odniesieniu do jej stanu:

Dodawanie encji do kontekstu:
Dodawać można na jeden z trzech sposobów:
za pomocą metody Add

Code:
            using (var context = new AdventureWorksLTEntities())
            {
                var customer = new Customer {FirstName = "Jacek", LastName = "Kowalski"};
                context.Customers.Add(customer);
                context.SaveChanges();
            }

zmieniając stan encji na Added:

Code:
            using (var context = new AdventureWorksLTEntities())
            {
                var customer = new Customer {FirstName = "Jacek", LastName = "Kowalski"};
                context.Entry(customer).State = System.Data.EntityState.Added;
                context.SaveChanges();
            }

trzecia możliwość to dodanie do kolekcji pobranych elementów, np. klient może mieć wiele zamówień, chcemy dodać kolejne - możemy postąpić następująco:

Code:
            using (var context = new AdventureWorksLTEntities())
            {
                var salesOrders = context.Customers.First().SalesOrderHeaders;
                salesOrders.Add(new SalesOrderHeader { AccountNumber = "1111111111111", DueDate = DateTime.Now, SubTotal = 100 });
                context.SaveChanges();
            }

W każdym przypadku, jeżeli dodawana encja posiada referencje do innych encji, zostaną one także dodane do bazy danych podczas wywoływania SaveChanges - chyba że już są zapisane te dane w bazie danych.


Dołączanie encji do kontekstu
Jeżeli mamy encję, która istnieje w bazie danych, ale z jakichś powodów została odłączona od kontekstu (np. została wysłana przez klienta w n-warstwowej aplikacji), wtedy taką encję możemy dołączyć do kontekstu za pomocą metody Attach:

Code:
            var customer = GetCustomerFromRepository();
            using (var context = new AdventureWorksLTEntities())
            {
                context.Customers.Attach(customer);
                context.SaveChanges();
            }

Encja zostanie dodana ze stanem Unchanged, a wywołanie metody SaveChanges w tym przypadku nie będzie mieć żadnych konsekwencji na bazie danych.
Innym sposobem dodania istniejącej encji w bazie do kontekstu jest zmiana jej stanu na Unchanged:

Code:
            var customer = GetCustomerFromRepository();
            using (var context = new AdventureWorksLTEntities())
            {
                context.Entry(customer).State = System.Data.EntityState.Unchanged;
                context.SaveChanges();
            }

poniedziałek, 26 listopada 2012

Exchange Online - pobieranie adresu do Web Serviceu (EWS)

Microsoft Exchange Server to serwer poczty stworzony przez Microsoft. Aby napisać aplikację, która komunikuje się z Exchange-m można użyć udostępnionych web service tzw. EWS - Exchange Web Services. Aby połączyć się do web service należy najpierw zdobyć jego adres.
Instrukcja w jaki sposób poznać adres Exchange Online została przedstawiona poniżej:


  1. Logujemy się na nasze konto na stronie https://portal.microsoftonline.com
  2. Przechodzimy na zakładkę Outlook
  1.   Wybieramy Opcje -> Wszystkie opcje:



  1. Następnie wybieramy opcje Ustawienia dostępu do serwerów POP, IMAP i SMTP... 

  1.  W okienku które się pojawi kopiujemy któryś z trzech dostępnych adresów:
  1. Tworzymy adres do webserwisu według wzoru:
https://<skopiowany adres>/EWS/Exchange.asmx

czyli w moim przypadku będzie to:

https://aaa.outlook.com/EWS/Exchange.asmx


Mając adres możemy następnie podłączyć się do Exchange Online i tworzyć aplikacje dla niego.

niedziela, 25 listopada 2012

Łączenie się z bazą po SSH

Problem:
Baza danych (MySql) stoi na maszynie Unixowej, połączenie do niej możliwe tylko po SSH.

Problem niby prosty, tworzymy aplikację kliencką, która ma na celu prezentację wyników zapytań z bazy dnaych:



SSH służy tutaj jako zabezpieczenie przed dostępem do poufnych danych przez niepożądane osoby.

Problem więc należy rozwiązać w następujący sposób:
  • stworzyć bezpieczne połączenie SSH
  • przeforwardować nasz port lokalny na port zdalny gdzie pracuje baza danych
  • stworzyć połączenie do bazy danych - tutaj postępujemy tak jak zwykle, z tą różnicą iż teraz musimy połączyć się z naszym lokalnym komputerem, poprzez skonfigurowany w poprzednim punkcie port
Połączenie SSH możemy stworzyć na dwa sposoby:
  • skorzystać z aplikacji, którą uruchomimy jako osobny proces w tle np. PLINK
  • wykorzystać jedną z dostępnych bibliotek SSH
Pierwszy sposób jest dosyć łatwy w implementacji, jednak uruchamia w tle dodatkowy proces, który może nie być mile widziany.
Bibliotek do SSH dla .NET nie brakuje w sieci. Ja wybrałem SharpSSH, które można pobrać ze strony http://www.tamirgal.com/blog/page/SharpSSH.aspx (dział Download).
Do projektu należy dodać następujące DLL:
  • Tamir.SharpSSH.dll
  • Org.Mentalis.Security.dll
  • DiffieHellman.dll
Kod przykładowego połączenia:

Code:
            var client = new JSch();
            Session session = client.getSession("user_login", "host", 22);
            session.setHost("host");
            session.setPassword("password");
            var sshConfig = new Hashtable();
            sshConfig.put("StrictHostKeyChecking", "no");
            session.setConfig(sshConfig);
            session.connect();
            session.setPortForwardingL(3307, "localhost", 3306);

Następnie w połączeniu z bazą danych skorzystamy z portu 3307, oraz servera - localhost.

sobota, 24 listopada 2012

WPF: Data binding directly to a store query...

Korzystając  z DbContext i bindując bezpośrednio do wyniku zapytania, które zwraca IEnumerable<T>, otrzymywałem następujący błąd:



'Set property 'System.Windows.Controls.ItemsControl.ItemsSource' threw an exception.' Line number '54' and line position '45'.

Rozwijając InnerException można się dodatkowo dowiedzieć iż:

Data binding directly to a store query (DbSet, DbQuery, DbSqlQuery) is not supported. Instead populate a DbSet with data, for example by calling Load on the DbSet, and then bind to local data. For WPF bind to DbSet.Local. For WinForms bind to DbSet.Local.ToBindingList().

Rozwiązanie problemu jest dosyć proste - należy dane przed zbindowaniem do kontrolki pobrać z bazy danych, czyli np. użyć metod:
  • ToList
  • ToArray
Ponowne uruchomienie programu już nie spowoduje tego błędu.

czwartek, 22 listopada 2012

70-511 Rozdział 3 - Graficzny interfejs użytwkonika - zarządzanie kontrolkami w czasie działania aplikacji

W czasie działania aplikacji można zarówno dodawać, jak i usuwać kontrolki.
Windows Forms oferuje właściwość Controls, która pozwala na dodawanie bądź usuwanie kontrolek:

Code:
            //Adding new control to form in run time
            var newButton = new Button();
            newButton.Text = "My new button";
            this.Controls.Add(newButton);

            //Delete control in run time
            this.Controls.Remove(newButton);


W przypadku WPF należy skorzystać w zależności od typu kontrolki z właściwości:
  • dla kontrolek typu kontener - właściwość Children
  • dla kontrolek listowych właściwość Items
  • dla kontrolek "zawartościowych" - Content conotrls, poprzez właściwość Content

Przykład:

Code:
        public MainWindow()
        {
            InitializeComponent();
            var buttons = GetSampleButtons();
            //Adding to Container control
            grid1.Children.Add(buttons[0]);
            //Adding to List control
            lb1.Items.Add(buttons[1]);
            //Adding to content control
            btn1.Content = buttons[2];
        }

        private Button[] GetSampleButtons()
        {
            var buttons = new Button[3];
            for (int i = 1; i < 4; i++)
            {
                var newButton = new Button();
                newButton.Content = "My new button";
                newButton.Width = 100;
                newButton.Height = 20;
                newButton.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
                buttons[i - 1] = newButton;
            }

            return buttons;
        }


Xaml:

Code:
<Window x:Class="WpfApplication2.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 Name="grid1">
        <ListBox Name="lb1" Width="100" Height="50" VerticalAlignment="Top" />
        <Button Name="btn1" Width="100" Height="35" />
    </Grid>
</Window>







Usunięta kontrolka, jeżeli nie jest używana do niej referencja, zwolni zajmowaną pamięć.

70-511 Rozdział 3 - Graficzny interfejs użytwkonika - drzewo wizualne

WPF definiuje interfejs użytkownika jako tzw. drzewo wizualne (visual tree). Nazwa wzięta z dwóch powodów:
  • elementy tworzące interfejs, umiejscawiane są w postaci przypominającej strukturę danych drzewo
  • każdy element wizualny (widzialny) dziedziczy po klasie Visual
Klasa Visual zapewnia takie funkcjonalności jak transformacje, przycinanie czy też test kliknięcia (czy dany obiekt został kliknięty myszką). Dodatkowo zapewnia ona serializację grafiki, dzięki czemu interfejs jest bardziej responsywny. 
Aby ułatwić poruszanie (trawersowanie) po drzewie wizualny, dostępna jest statyczna klasa VisualTreeHelper. Niektóre z jej ważniejszych metod:

  • GetCacheMode - pobiera dane z cache dla danego obiektu wizualnego
  • GetChild - pobiera potomka danego rodzica, pod wskazanym indeksem
  • GetChildrenCount - pobiera ilość potomków danego obiektu
  • GetContentBounds - pobiera obszar zajmowany przez obiekt wizualny
  • GetDrawing - zwraca graficzną zawartość obiektu
  • GetEffect - zwraca efekty zastosowane na obiekcie
  • GetOffset - zwraca offset obiektu
  • GetOpacity - zwraca przeźroczystość
  • GetParent - zwraca rodzica danego obiektu
  • GetTransform - pobiera transformacje nałożone na obiekt

Przykład przejścia po wszystkich elementach wizualnych formy:

Code:
        public MainWindow()
        {
            InitializeComponent();
            Loop(grid);
        }

        private void Loop(Visual obj)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                var vObj = (Visual)VisualTreeHelper.GetChild(obj, i);
                tb.Text += vObj.GetType().Name + Environment.NewLine;
                Loop(vObj);
            }
        }


Efekt:







Xaml:

Code:
<Window x:Class="WpfApplication1.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 Margin="0,0,0,-49" Name="grid">
        <Rectangle Width="100" Height="100" Fill="Blue">
            <Rectangle.Clip>
                <EllipseGeometry RadiusX="30" RadiusY="30" Center="50, 50" />
            </Rectangle.Clip>
        </Rectangle>
        <TextBox x:Name="tb" HorizontalAlignment="Left" Height="218" Margin="25,66,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="153"/>
        <Label Content="Label" HorizontalAlignment="Left" Margin="383,66,0,0" VerticalAlignment="Top"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="396,167,0,0" VerticalAlignment="Top" Width="75"/>
    </Grid>
</Window>

czwartek, 15 listopada 2012

70-511 Rozdział 3 - Graficzny interfejs użytwkonika - transformacje

Transformacje to obiekty, które umożliwiają zmianę kształtu przez zmianę jego współrzędnych.
Rodzaje transformacji:

RotateTransform
Obrócenie kształtem wokół współrzędnych X,Y o zadany kąt. Przykład poniżej prezentuje zwyczajny prostokąt (niebieski) oraz czerwony po nałożeniu transformacji:

Code:
        <Rectangle Fill="Blue" Width="50" Height="50" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Center"></Rectangle>

        <Rectangle Fill="Red" Width="50" Height="50" Margin="80" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Rectangle.RenderTransform>
                <RotateTransform CenterX="25" CenterY="25" Angle="45" />
            </Rectangle.RenderTransform>
        </Rectangle>

Efekt:


ScaleTransform
Skalowanie kształtu:


Code:
        <Rectangle Fill="Blue" Width="50" Height="50" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Center"></Rectangle>

        <Rectangle Fill="Red" Width="50" Height="50" Margin="150" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Rectangle.RenderTransform>
                <ScaleTransform CenterX="25" CenterY="25" ScaleX="2" ScaleY="2.5" />
            </Rectangle.RenderTransform>
        </Rectangle>

Efekt:



SkewTransform
Pochylenie kształtu w pionie i poziomie:



Code:
        <Rectangle Fill="Blue" Width="50" Height="50" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Center"></Rectangle>

        <Rectangle Fill="Red" Width="50" Height="50" Margin="150" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Rectangle.RenderTransform>
                <SkewTransform AngleX="50"></SkewTransform>
            </Rectangle.RenderTransform>
        </Rectangle>


Efekt:



TranslateTransform
Przesuwa układ współrzędnych o zadane X i Y:

Code:
        <Rectangle Fill="Blue" Width="50" Height="50" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Center"></Rectangle>

        <Rectangle Fill="Red" Width="50" Height="50" Margin="150" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Rectangle.RenderTransform>
                <TranslateTransform X="50" Y="90" />
            </Rectangle.RenderTransform>
        </Rectangle>

Efekt:



TransformGroup
Pozwala nałożyć na obiekt kilka transformacji jednocześnie:

Code:
        <Rectangle Fill="Blue" Width="50" Height="50" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Center"></Rectangle>

        <Rectangle Fill="Red" Width="50" Height="50" Margin="150" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <TranslateTransform X="50" Y="40" />
                    <SkewTransform AngleX="30" AngleY="20" />
                    <RotateTransform Angle="15" />
                </TransformGroup>
            </Rectangle.RenderTransform>
        </Rectangle>

Efekt:



MatrixTransform
Tworzy macierz 3x3, która pozwala na definiowanie własnych transformacji:

Code:
        <Button Width="50" Height="50">
            <Button.RenderTransform>
                <MatrixTransform>
                    <MatrixTransform.Matrix>
                        <Matrix>1 0 0 1 10 10</Matrix>
                    </MatrixTransform.Matrix>
                </MatrixTransform>
            </Button.RenderTransform>
        </Button>

Efekt:

Więcej o macierzy można znaleźć na stronie http://msdn.microsoft.com/en-us/library/system.windows.media.matrixtransform.aspx



Wszystkie transformacje domyślnie mają miejsce w lewym górnym rogu transformowanego kształtu. Współrzędne tego punktu określone są jako (0,0). Prawy dolny róg ma współrzędne (1,1). Aby zmienić punkt rozpoczęcia transformacji należy ustawić właściwość RenderTransformOrigin="0.5,0.5"



Rzut elementu - Flipping
Aby "rzucić" elementem należy skorzystać z ScaleTransform. Jeżeli chcemy rzucić kształtem horyzontalnie, ustawiamy właściwość ScaleX na -1, jeżeli chcemy rzucić wertykalnie ScaleY na -1. Rzucenie w obydwu kierunkach jest możliwe po ustawieniu ScaleX i ScaleY na -1.Przykład:

Code:
        <Button Height="50" Width="100" VerticalAlignment="Top">
            <Button.RenderTransform>
                <ScaleTransform ScaleX="-1"></ScaleTransform>
            </Button.RenderTransform> Flipped Button
        </Button>

Efekt:




Przycinanie - Clipping
Przycinanie nie zmniejsza obszaru zajmowanego przez kształt, a jedynie zmniejsza widoczną powierzchnię do powierzchni przycinającej figury. Przykład:

Code:
        <Rectangle Width="100" Height="100" Fill="Blue">
            <Rectangle.Clip>
                <EllipseGeometry RadiusX="30" RadiusY="30" Center="30, 50" />
            </Rectangle.Clip>
        </Rectangle>

Efekt:


środa, 14 listopada 2012

jQuery - proste animacje

Animacje na stronach to już nie tylko Flash, Silverligh czy Applet ale coraz częściej JavaScript.
jQuery udostępnia wiele gotowych animacji, jak również dostarcza prostą metodę do definiowania nowych.

Niektóre z gotowych efektów/animacji do wykorzystania:
  • show() - pokazuje element jeżeli jest ukryty
  • hide() - ukrywa element
  • toggle() - przełącznik, np przełącza daną właściwość naprzemiennie
  • slideDown() / slideUp() - efekt zjeżdżania w dół / górę
  • fadeIn() - rozjaśnianie

Aby tworzyć własne animacje, możemy skorzystać z funkcji animate():

.animate( properties [, duration] [, easing] [, complete] ) 

np.

Code:
$("mydiv").animate({ left: "100px" }, 500);

Należy przy tym pamiętać, że metoda animate działa tylko z elementami CSS które są wielkościami liczbowymi jak np. wielkość, położenie.

Bardzo fajne przykłady animacji można znaleźć na stronie http://designreviver.com/tutorials/20-easy-to-learn-jquery-animation-tutorials/
W internecie można znaleźć wiele tutoriali, pokazujących w jaki sposób tworzyć ciekawe animacje i efekty.

70-511 Rozdział 3 - Graficzny interfejs użytwkonika - kształty - Kształty

Kształty to graficzne prymitywy. Wszystkie kształty w WPFie dziedziczą po klasie Shape, która dziedziczy po klasie Visual. Niektóre z jej właściwości:
  •  Fill - wypełnianie
  •  Stroke - kolor obramowania
  • StrokeThickness - grubość obramowania
  • Stretch - określa jak kształt wypełnia dostępną ptrzestrzeń

Rectangle i Ellipse
Dwa podstawowe kształty: prostokąt i elipsa:


Code:
<Rectangle Height="100" Width="200" Fill="Blue"/>
<Ellipse Height="100" Width="200" Fill="Blue"/>

Jeżeli nie zostanie ustawiona wartość Height i Width można użyć właściwości Stretch w celu określenia jak kształt ma wypełnić wolną przestrzeń. Aby uzyskać zaokrąglone krawędzie można użyć właściwości RadiusX oraz RadiusY


Line i Polyline
Linia używa współrzędnych relatywnych do kontenera w którym jest malowana:


Code:
<Line Stroke="Red" X1="0" Y1="50" X2="100" Y2="440"/>

Polyline reprezentuje linię przebiegającą przez wyspecyfikowanie punkty. Pierwszy punkt jest początkiem, ostatni końcem:


Code:
<Polyline Stroke="Green"
Points="300, 300 400, 400 400, 300 500, 400 500, 300"/>

Przecinki między parami X,Y nie są wymagane jednak zwiększa się dzięki nim czytelność kodu.


Polygon
Wielokąt jest podobny do Polyline, z tym że dodatkowo łączy pierwszy punkt z ostatnim oraz pozwala wypełnić zdefiniowany wielokąt poprzez właściwość Fill:


Code:
<Polygon Fill="Green"
Points="300, 300 400, 400 400, 300 500, 400 500, 300"/>

Jeżeli linie w wielokącie się krzyżują w jaki sposób jest wypełniany kolorem decyduje właściwość NonZero , które może przyjąć następujące wartości:
  • EvenOdd - zliczana jest ilość linii potrzebna do dostania się do ograniczonego obszaru. Jeżeli zamknięty obszar można wyznaczyć przez nieparzystą ilość linii jest on wypełniany, w przeciwnym przypadku nie jest wypełniany.
  • NonZero - zliczana jest ilość linii potrzebnych do dostania się do zamkniętego obszaru oraz ich kierunek.
Na temat FillRule można więcej poczytać pod adresem: http://msdn.microsoft.com/en-us/library/system.windows.media.fillrule.aspx



Path
Path jest najbardziej skomplikowanym rodzajem kształtu. Opisuje skomplikowane kształty złożone z innych podstawowych kształtów. W Path możemy użyć następujące typy geometryczne:
  • CombinedGeometry - pozwala połączyć dwa obiekty typu Geometr
  • EllipseGeometry - dane opisujące elipsę
  • LineGeometry - reprezentuje linię
  • PathGeometry - reprezentuje obiekt złożony z wielu linii, łuków i krzywych
  • RectangleGeometry - reprezentuje prostokąt
  • StreamGeometry - odpowiednik PathGeometry z tą różnicą, że tylko do odczytu 
Przykład:

Code:
        <Path Fill="Blue" Margin="50">
            <Path.Data>
                <EllipseGeometry RadiusX="40" RadiusY="40" />
            </Path.Data>
        </Path>

Klasa CombinedGeometry pozwala stworzyć obiekt złożony z wielu figur. Sposób ich łączenia determinuje właściwość GeometryCombineMode która może przyjąć następujące wartości:
  • Exclude - odjęcie drugiego kształtu od pierwszego
  • Intersect - przecięcie, czyli część wspólna
  • Xor - przestrzeń nie dzielona wspólnie między figurami
  • Union - suma

wtorek, 13 listopada 2012

async, await - przechwytywanie wyjątków

Łapanie wyjątków w metodzie asynchronicznej nie jest niczym skomplikowanym. Należy tylko pamiętać o tym, iż mamy do czynienia z różnymi możliwymi scenariuszami wyjątków.
Metoda oznaczona słowem kluczowym async zawiera przeważnie jedną lub więcej wywołań metod ze słowem kluczowym await. Await stoi przed metodą zwracającą typ Task lub Task<TResult>.
Pierwsza zasada to ta, iż await nie może się pojawić się w bloku catch lub finally.
Rezultat - Task - na który oczekujemy może przejść do stanu błędu:

Code:
        static void Main(string[] args)
        {
            var i = DoSomeWork();
        }

        static async Task<int> DoSomeWork()
        {
            int res = 0;
            var task = Length();
            try
            {
                res = await task;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.WriteLine("----------------------");
            Console.WriteLine("Is canceled: " + task.IsCanceled);
            Console.WriteLine("Is completed: " + task.IsCompleted);
            Console.WriteLine("Is fauled: " + task.IsFaulted);

            return res;
        }

        static async Task<int> Length()
        {
            throw new Exception();
        }





Zgłoszono wyjątek typu 'System.Exception'.
----------------------
Is canceled: False
Is completed: True
Is fauled: True


Tak może także przejść do stanu Canceled - anulowany. Metoda w takim przypadku rzuci wyjątek OperationCanceledException:

Code:
        static void Main(string[] args)
        {
            var i = DoSomeWork();
        }

        static async Task<int> DoSomeWork()
        {
            int res = 0;
            var task = Length();
            try
            {
                res = await task;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.WriteLine("----------------------");
            Console.WriteLine("Is canceled: " + task.IsCanceled);
            Console.WriteLine("Is completed: " + task.IsCompleted);
            Console.WriteLine("Is fauled: " + task.IsFaulted);

            return res;
        }

        static async Task<int> Length()
        {
            throw new OperationCanceledException();
        }






Operacja została anulowana.
----------------------
Is canceled: True
Is completed: True
Is fauled: False

poniedziałek, 12 listopada 2012

jQuery zdarzenia

Zdarzenia w jQuery obsługuje się bardzo prosto.

Istnieją dwie proste metody bindowania, w zależności od kontekstu w którym je wykorzystamy:

$("element").metoda(function()) - jeżeli dany element DOM istnieje na stronie np.


Code:
@{
    ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>

<div id="List">
</div>
<input type="button" value="Przycisk" id="przycisk"/>
<script type="text/javascript">
    $(document).ready(function () {
        $("#przycisk").click(function () {
            $("#List").append("Text");
            return false;
        });
    })
</script>

W tym przypadku przycisk istnieje już na formatce i dodajemy do niego zdarzenie.

W przypadku gdy element nie istnieje na stronie i chcemy dynamicznie dodać do niego zdarzenie, korzystamy z metody .on("event", function(event){}). Przykład:


Code:
<div id="List">
    <p>Click me!</p>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        $("#List").on("click", "p", function () {
            $("#List").append('<p>Click Me!<p/><br/>');
        });
    })
</script>

W tym przypadku dodajemy do formularza kolejne paragrafy, które mają automatycznie zbindowane zdarzenie Click.


Inne przydatne metody:
.one() - binduje zdarzenie na jedno użycie (po pierwszym wywołaniu zdarzenie jest usuwane z elementu)
.unbind([nazwa_eventu]) - usuwa jedno bądź też wszystkie (brak nazwy_eventu) zdarzenia z elementu
$("element").trigger("click") - wywołanie ręczne zdarzenia

niedziela, 11 listopada 2012

async, await - przetwarzanie metody asynchronicznej

Zaczniemy znów od kawałka kodu:

Code:
        public async Task<int> GetDataLengthAsync()
        {
            var client = new HttpClient();
            var taskResult = client.GetStringAsync("http://onet.pl");
            DoSomeStaff();
            var pageContent = await taskResult;

            return pageContent.Length; 
        }

        private void DoSomeStaff()
        {
            Console.WriteLine("Doing something");
        }

Przeanalizujmy w jaki sposób wykonywana jest powyższa metoda:
  1. Następuje wywołanie metody GetDataLengthAsync - np z wywołania zdarzenia Click przycisku
  2. Zostaje utworzony obiekt klasy HttpClient i wywołana na nim metoda GetStringAsync
  3. Metoda GetStringAsync jest metodą blokującą - musi oczekiwać na odpowiedź serwera w celu pobrania kodu źródłowego strony. Metoda ta zwraca w rezultacie Task<string>, który jest następnie przypisywany do zmiennej taskResult.
  4. Ponieważ nie potrzebujemy na ten moment rezultatu ze zmiennej taskResult, kod jest wykonywany dalej i zostaje wywołana asynchroniczna metoda DoSomeStaff(). Metoda ta po wykonaniu powraca do metoday GetDataLengthAsync.
  5. Przechodzimy do sedna metody: metoda chce zwrócić długość łańcucha kodu źródłowego strony. Aby to zrobić, musi otrzymać łańcuch z metody GetStringAsync. Słowo kluczowe await mówi: teraz się zatrzymaj i czekaj na wynik zadania taskResult.
  6. GetStringAsync zwraca rezultat - pamiętajmy, że nie jest to string, a Task<string>. Operator await niejako "wyciąga" rezultat i przypisuje go do zmiennej odpowiedniego typu tj string.
  7. Następuje obliczenie długości i zwrócenie jej do zdarzenia, które wywołało metodę GetDataLengthAsync

Tak wygląda przebieg metody asynchronicznej w nowym .NET. Warto przeanalizować kilka przykładów, aby lepiej zrozumieć cały mechanizm.

sobota, 10 listopada 2012

await, async - konwencje i fakty

Nietypowo, na początek trochę kodu:

Code:
        public async Task<int> GetDataLengthAsync()
        {
            var client = new HttpClient();
            var taskResult = client.GetStringAsync("http://onet.pl");
            DoSomeStaff();
            var pageContent = await taskResult;

            return pageContent.Length; 
        }

        private void DoSomeStaff()
        {
            Console.WriteLine("Doing something");
        }

Co czyni powyższą metodę asynchroniczną?
  • sygnatura metody zawiera słowo kluczowe async
  • nazwa metody zawiera przyrostek Async
  • typ zwracany to:
    • Task<TResult>
    • Task
    • void
  • metoda zawiera przynajmniej jedno słowo kluczowe await
.NET 4.5 zawiera wiele metod asynchronicznych i poznać je możemy właśnie po przyrosku Async. 

Fakty związane z async i await:

  • Należy pamiętać że await nie tworzy nowego wątku. Jeżeli chcemy, aby został stworzony nowy wątek można skorzystać z nowej metody Task.Run, która jest skrótem od Task.Factory.StartNew.
  • Jeżeli metoda nie zawiera, żadnego słowa kluczowego await, będzie wykonywana tak jak zwykła metoda synchroniczna. Ze strony kompilatora zostanie zgłoszone jedynie ostrzeżenie o takim fakcie. 
  • Jeżeli metoda zwraca Task dostajemy informację o stanie zadania, rezultat bądź też wyjątek co poszło nie tak podczas wykonywania naszego kodu.
  • Metoda async nie może przyjmować parametrów przekazywanych przez referencję (ref). Może jednak w sobie wywoływać metody, przyjmujące parametry w ten sposób.

czwartek, 8 listopada 2012

Asynch await - asynchroniczność w .NET 4.5

Zamrażanie interfejsu użytkownika podczas wykonywania skomplikowanej czynności nie jest dobrym pomysłem. Aplikacja, która "zamiera" nie zachęca do dalszego wykorzystywania przez użytkownika. Programowanie asynchroniczne z drugiej strony wiąże się z większym nakładem pracy oraz bardziej skomplikowanym kodem wynikowym.
Na pomoc przychodzi .NET 4.5 wraz z nowymi słowami kluczowymi: async, await. Jak je stosować i w jaki sposób pomagają nam tworzyć aplikacje asynchroniczne zobaczymy w poniższym przykładzie.

Tworzymy zwykłą aplikację typu Windows Forms. Kładziemy na formatkę kontrolkę Button oraz Label. Oprogramowujemy zdarzenie kliknięcia przycisku:


Code:
        private void button1_Click(object sender, EventArgs e)
        {
            var result = SynchMethod();
            label1.Text = result;
        }

        private string SynchMethod()
        {
            Thread.Sleep(5000);
            return "Done";
        }

Uruchamiamy program, naciskamy przycisk. Jeżeli w tym momencie spróbujemy przesunąć okienko programu nie uda się nam to, aż do czasu pojawienia się na Label-u napisu Done. Dzieje się tak dlatego, ponieważ główny wątek został zamrożony na 5 sekund. Obrazuje to przykładową sytuację pobierania danych z Web Service.
Powyższą metodę w kilku krokach można przerobić z synchronicznej na asynchroniczną dzięki czemu nasz interfejs nie zostanie zamrożony:

Code:
        private async void button1_Click(object sender, EventArgs e)
        {
            var result = await AsynchMethod();
            label1.Text = result;
        }

        private string SynchMethod()
        {
            Thread.Sleep(5000);
            return "Done";
        }

        private Task<string> AsynchMethod()
        {
            var t = new Task<string>(SynchMethod);
            t.Start();

            return t;
        }

Co się tutaj zmieniło?
Dodaliśmy metodę AsynchMethod która zwraca Task<string> czyli tak na prawdę tworzony jest tutaj opakowany wątek  w którym jest wywoływana nasza metoda.
Metoda button1_Click otrzymała słówko kluczowe async oznaczające że metoda ta ma zostać wykonana asynchronicznie.
Metoda AsynchMethod została poprzedzona słówkiem await. Słówko to oznacza zapowiedź tego, iż zostanie zwrócony wynik w nieokreślonej przyszłości. Po jego zwróceniu mają się wykonać kolejne linijki kodu.
Przykład ten jest bardzo prosty - taki miał być w zamiarze. Obrazuje w jaki sposób pisać własne metody asynchroniczne.
Jest to ważne z punktu widzenia pisania aplikacji, które chcemy umieścić w sklepie Microsot. Aby móc sprzedawać w nim swoje aplikacje, należy przejść certyfikację. Jednym z punktów które należy zaliczyć aby otrzymać certyfikat jest ten mówiący o tym, iż każda metoda trwająca powyżej 50 milisekund musi być wywołana w sposób asynchroniczny.

Warto więc już teraz zacząć programować asynchronicznie, aby w późniejszym czasie nie tracić czasu na poprawianie kodu.

Page Inspector

Tworząc aplikację webową, cyklicznie wykonujemy czynność kodowania, a następnie sprawdzania jak wygląda efekt w przeglądarce.
Jeżeli wystąpi błąd najczęściej korzystamy z tzw. narzędzi deweloperskich dostarczanych jako funkcjonalność przeglądarki bądź też plugin (np. FireBug dla Firefox). Cykl ten powtarza się dopóki błąd nie zostanie ostatecznie poprawiony, bądź też żądana funkcjonalność nie osiągnie finalnego wyglądu.
Nowy VS 2012 wprowadza narzędzie Page Inspector, które w zamierzeniu ma zastąpić narzędzia dostępne w przeglądarkach oraz dodać kilka dodatkowych opcji. Dlaczego ma być bardziej innowacyjne od obecnie oferowanych w przeglądarkach? Dzięki Integracji z IDE.
Narzędzie uruchamia się w środowisku VS 2012. Dzięki temu nie opuszczamy ani na chwilę kodu naszej aplikacji.
Wygląd Page Inspector przedstawia poniższy zrzut:






Możliwości narzędzia:

  • narzędzia deweloperskie znane z przeglądarek przeniesione bezpośrednio do okna VS
  • podgląd plików - pokazuje pliki po stronie serwera użyte do renderowania strony
  • manipulacja stylami CSS

poniedziałek, 5 listopada 2012

DOCTYPE w projekcie webowym, oraz testy w wielu przeglądarkach

DOCTYPE - Document Type Declaration - definiuje formalną strukturę dokumentu. Dzięki temu, możemy sprawdzić czy stworzony przez nas dokument jest poprawny pod względem składni. Dla stron HTML wprowadzono kilka standardowych definicji DOCTYPE.
Visual udostępnia automatyczne sprawdzanie składni dokumentu HTML. Do tej pory aby funkcja działała należało wybrać ją z ComboBoxa. W nowym Visualu 2012 wystarczy wpisać odpowiednią deklarację, a odpowiednia wartość zostanie sama wybrana z Comboboxa:






Dodatkowo, bez wymagania żadnej kompilacji, środowisko podpowie, które tagi nie są zgodne z danym DOCTYPE:


Drugim fajnym dodatkiem jest możliwość testów naszej strony pod różnymi przeglądarkami. Aby sprawdzić jak nasza strona wygląda np. pod IE wystarczy wybrać ją z listy:


Visual Studio automatycznie wykryje wszystkie zainstalowane w systemie przeglądarki i doda je do listy pozwalając na szybkie testowanie aplikacji w różnych środowiskach.

Szybkie wyszukiwanie opcji - Quick Launch

Jak często zdarza się, że szukamy jakiejś opcji w IDE i nie możemy znaleźć miejsca w którym się ona znajduje? IDE jakim jest VS przez lata ewolucji rozrosło się do tak dużych rozmiarów, że znalezienie odpowiedniej funkcjonalności może zająć całkiem sporo czasu.
Microsoft zauważył ten problem i w nowym VS 2012 wprowadził Quick Launch, który zaznaczony jest na poniższym screeenie:


W jaki sposób działa nowa wyszukiwarka?
Powiedzmy że chcemy znaleźć miejsce w którym ustawiane są kolory czcionek w IDE. Wpisujemy więc frazę Color a w odpowiedzi otrzymujemy:


Proste, szybkie i skuteczne. Nasza wyszukiwarka przeszukuje oczywiście nie tylko opcje ale także polecenia dostępne w meni. Dla przykładu po wpisaniu intelli otrzymamy następujące podpowiedzi:


Kolejnym ciekawym aspektem jest możliwość wyszukiwania wśród otwartych plików. Zobaczmy na przykład, w projekcie mamy plik Person.cs który jest otwarty na zakładce ale nie aktywny. Wpisujemy nazwę i otrzymujemy podpowiedź:






Funkcjonalność ta nie wyszukuje w zawartości pliku. Szukanie dotyczy tylko i wyłącznie nazwy pliku.

W opcjach


Możemy kolejno:

  • wyłączyć pasek wyszukiwania
  • ostatnio wyszukiwane frazy nie będą kasowane
  • wybrać kategorie które będą obsługiwane przez Quick Launch

Narzędzie bardzo fajne i godne polecenia.

niedziela, 4 listopada 2012

Operacje na zbiorach

Kod źródłowy do pobrania: https://skydrive.live.com/redir?resid=BCCBFB57B3C672D0!117

Biblioteka .NET dostarcza wiele ułatwień w dziedzinie pracy nad zbiorami.
W ramach przypomnienia matematyki:



Do pracy ze zbiorami możemy podejść na dwa sposoby:
  1. Metody LINQ
  2. Kolekcja HashSet<T>
Kiedy wybrać operacje LINQ:
  • takie same wartości w kolekcji są dopuszczalne
  • nie chcemy modyfikować istniejącej kolekcji (źródła) - zwracamy IEnumerable<T>
Kiedy kolekcja HashSet<T>:
  • nie mogą się pojawić te same wartości więcej niż raz
  • chcemy modyfikować oryginalną kolekcję

Metody LINQ:
Concat - sumuje dwa zbiory, dopuszczając do zduplikowanych wartości:

Code:
            int[] set1 = { 1, 2, 3 };
            int[] set2 = { 4, 5, 3 };

            var result = set1.Concat(set2);


Union - sumuje dwa zbiory, jako rezultat zwracając elementy unikalne w obu zbiorach:

Code:
            int[] set1 = { 1, 2, 3 };
            int[] set2 = { 4, 5, 3 };

            var result = set1.Union(set2);


Distinct - zwraca tylko elementy unikalne:

Code:
            int[] set1 = { 1, 2, 3, 3, 4, 5, 3, 2, 1, 4, 5, 6, 7, 4, 5, 6, 3 };

            var result = set1.Distinct();


Expect - różnica - wartości w pierwszym zbiorze, które nie występują w drugim:

Code:
            int[] set1 = { 1, 2, 3 };
            int[] set2 = { 4, 5, 3 };

            var result = set1.Except(set2);


Intersect - przecięcie zbiorów czyli część wspólna:

Code:
            int[] set1 = { 1, 2, 3, 4 ,5 };
            int[] set2 = { 4, 5, 3 };

            var result = set1.Intersect(set2);


Rezultaty operacji:




Kolekcja HashSet<T>
Kolekcja ta została dodana w .NET wersji 3.5 czyli można rzec "dość późno". Jest to kolekcja oparta na kluczach, zawierająca tylko wartości unikalne. Dzięki swojej budowie operacje wyszukiwania, sprawdzania czy dany element już istnieje w kolekcji czy też usuwanie elementu mają złożoność liniową O(1). Operacje wywoływane na kolekcji powodują zmianę oryginalnej kolekcji. Aby odróżnić metody LINQ od HashSet<T> metody kolekcji posiadają słówko With np. UnionWith, IntersectWith:

Code:
            var set1 = new HashSet<int>(new int[] { 1, 2, 3 });
            var set2 = new HashSet<int>(new int[] { 3, 4, 5 });
            set1.UnionWith(set2);




Porównanie metod dla metod LINQ i kolekcji HashSet<T>:


Oczywiście metody które nie występują w LINQ łatwo można dopisać, np. dla operacji SetEquals kod LINQ będzie wyglądać następująco:

Code:
a.Distinct().OrderBy(x => x).SequenceEqual(b.Distinct().OrderBy(y => y));

czwartek, 1 listopada 2012

Chmura prywatna

Chmura prywatna - pojęcie to jest związane ze zwyczajną chmurą obliczeniową.Tak więc oprócz skalowalności, elastyczności oraz samoobsługi otrzymujemy dodatkową kontrolę i personalizację.



Microsoft w ramach prywatnej chmury umożliwia realizowanie dwóch modeli usług:
  • IaaS - infrastruktura jako usługa - korzystanie z zasobów infrastruktury jako usług
  • PaaS - platforma jako usługa - dostęp do konkretnej platformy aplikacji
 Zalety chmury prywatnej:
  • Pule zasobów - zasoby chmury (moc obliczeniowa, pamięć, przepustowość) mogą być dynamicznie przydzielane w zależności od aktualnych potrzeb
  • Samoobsługa - usługi zarówno po stronie klienta jak i usługodawcy są zarządzane poprzez interaktywny portal, który pozwala na automatyczne przydzielanie usług
  • Elastyczność - zasoby z puli mogą być bardzo szybko przydzielane i zmieniane w zależności od aktualnych wymagań usługi. Stają się dzięki temu skalowalne zarówno w górę jak i dół. 
  • Personalizacja i kontrola - zasoby prywatnej chmury przeznaczone są wyłącznie dla wykupującej jej jednostki, dzięki czemu mamy większą kontrolę nad architekturą chmurową oraz szerszą personalizację
Najważniejszą zaletą jednak jest to, iż płacimy za realne wykorzystane zasoby chmury, a nie za elementy których nie wykorzystamy.