piątek, 4 maja 2012

70-511 Rozdział 1 - Tworzenie interfejsu użytwkownika - Panele i układ

W tej części zajmiemy się powtórką związaną z kontenerami wykorzystywanymi podczas ustawiania kontrolek na formatce.

Podstawowe właściwości wszystkich kontrolek związanych z układem:
  • FlowDirection - kierunek w którym tekst jak i zawartość innych kontrolek będzie wyświetlany
  • Height - wysokość; domyślnie Auto
  • HorizontalAlignment - wyrównanie w poziomie (chodzi o rodzica kontrolki - parent)
  • HorizonalContentAlignment - wyrównanie zawartości kontrolki
  • Margin - margines
  • MaxHeight - maksymalna wysokość
  • MaxWidth - maksymalna szerokość
  • MinHeight - minimalna wysokość
  • MinWidth - minimalna szerokość
  • Padding - ilość spacji pomiędzy kontrolką i kontrolkami przechowywanymi w niej
  • VerticalAlignment - położenie pionowe
  • VerticalContentAlignment - położenie pionowe elementów wewnątrz kontrolki
  • Width - szerokość

Grid
Najczęściej używana kontrolka. Pozwala na definiowanie wierszy i kolumn.
Kontrolki wewnątrz Grid-a otrzymują dodatkowe właściwości które mówią w których kolumnach i wierszach mają się znaleźć. Właściwości te to:
  • Grid.Row - wiersz
  • Grid.Column - kolumna
  • Grid.RowSpan - ile wierszy ma zająć kontroka
  • Grid.ColumnSpan - ile kolumn ma zająć
GridSplitter - kontrolka umożliwiająca zmienianie wielkości wierszy i kolumn podczas działania programu. Najważniejsze właściwości GridSplitter:
  • Grid.Column - określa w której kolumnie znajdzie się GridSplitter
  • Grid.ColumnSpan - określa przez ile kolumn ma przebiegać GridSplitter - dla poziomego GridSplittera jego wartość powinna być równa ilości zdefiniowanych kolumn w Gridzie
  • Grid.Row - określa w którym wierszu ma się znaleźć GridSplitter
  • Grid.RowSpan - określa przez ile wierszy ma przebiegać GridSplitter - dla pionowego GridSplittera jego wartość powinna być równa ilości zdefiniowanych wierszy w Gridzie
  • Height - określa wysokość GridSplittera - dla pionowego powinna ona wynosić Auto
  • HorizontalAlignment - określa poziome położenie GridSplittera. Dla poziome powinna mieć wartość Stretch, dla pionowego - Top lub Bottom
  • Margin - Określa margines pomiędzy GridSplitterem a kontrolkami - typowo 0
  • ResizeBehavior - określa które kolumny lub wiersze są przeskalowane w stosunku do kolumny lub wiersza, dla których GridSplitter jest zdefiniowany. Domyślnie BasedOnAlignment, który określa zmianę rozmiaru na podstawie wierszy i kolumn do których przylega GridSplitter
  • ResizeDirection - określa czy zwiększane są kolumny/wiersze. Domyślnie ustawione jest Auto co jest równoważne zmianie wielkości na podstawie pozycji GridSplittera
  • ShowsPreview - decyduje czy GridSplitter ma aktualizować wielkość kolumny.wiersza w czasie interakcji z użytkownikiem
  • VerticalAlignment - Ustala poziome ułożenie GridSplittera. Dla pionowego ustawienie powinno mieć wartość Stretch, dla poziomego Left or Right
  • Width - określa szerokość GridSplittera. Dla poziomego ustawienie powinno mieć wartość Auto  

Lista kroków które należy wykonać aby poprawnie wstawić GridSplitter:
  1. Przeciągamy z przybornika kontrolkę GridSplittera do komórki w której chcemy żeby się znalazł
  2. Ustawiamy jego margines na 0
  3. Dla pionowego GridSplittera ustawiamy właściwość VerticalAlignment na Stretch. Dla poziomego ustawiamy HorizontalAlignment na Stretch. Drugą właściwość ustawiamy tak jak chcemy aby zachowywał się nasz GridSplitter
  4. Dla poziomego GridSplittera ustawiamy właściwość Width na Auto a Height na 2 lub więcej. Dla pionowego ustawiamy odpowiednio właściwość Height.
  5. Dla pionowego ustawiamy właściwość Grid.RowSpan na ilość wierszy w Gridzie którym się znajduje dla poziomego Grid.ColumnSpan na ilość kolumn


UniformGrid Control
Tworzy jednolity Grid, którego komórki mają jednakową wielkość. Możemy ustawić ilość wierszy i kolumn w nim. Dodając kolejne kontrolki do niego są wstawiane do kolejnych komórek.


StackPanel
Ustawia kontrolki jak na stosie - jedna po drugiej. Możliwe jest dodawanie ich w orientacji pionowej jak i poziomej poprzez właściwość Orientation


WrapPanel
Dodaje kolejne kontrolki w poziomych "paskach". Kiedy w jednym wierszy już się nie mieszczą są dodawane do kolejnego. Za pomocą właściwości FlowDirection można zmienić kierunek dodawania kontrolek.


DockPanel
Pozwala na dokowanie kontrolek, przypisując je do odpowiednich brzegów. Jest to rozwiązanie dobrze znane z WindowsForms. Posiada dodatkowo właściwość LastChildFill, która powoduje że ostatnia kontrolka zajmuje całą dostępną powierzchnię.


Canvas
Pozwala na umieszczanie kontrolek poprzez ustawienie koordynat. Podczas zwiększania/zmniejszania rozmiaru Canvasu kontrolki pozostają na swoich miejscach.


Dostęp do kontrolek zawartych w danym kontenerze odbywa się poprzez właściwość Children i indeks kontrolki której referencję chcemy otrzymać.

70-511 Rozdział 1 - Tworzenie interfejsu użytwkownika - kontrolki zaawansowane

W tej części zajmiemy się kontrolkami, mogącymi przechowywać wiele elementów.

ListBox
Kontrolka zaprojektowana aby wyświetlać listy, której elementy są typu ListBoxItem. Kontrolka automatycznie dodaje potrzebne paski przewijania jeżeli są potrzebne. Domyślnie można zaznaczyć tylko jeden element na liście, ustawiając właściwość SelectionMode można uzyskać dodatkowe możliwości:
  • Single - domyślna wartość - zaznaczanie pojedynczego elementu
  • Multiple - możliwość zaznaczenia wielu elementów
  • Extended - użytkownik może zaznaczyć kilka sąsiadujących elementów za pomocą klawisza Shift, lub kilka niesąsiadujących za pomocą klawisza CTRL.

ComboBox
Kontrolka różni się od poprzedniej tylko sposobem prezentacji elementów - jest to rozwijana lista z której wybieramy elementy. Listę możemy otworzyć z poziomu kodu ustawiając właściwość IsDropDownOpen na True.


TreeView i TreeViewItem
Pozwala na wyświetlanie list w postaci drzewiastej. Kontrolka TreeViewItem służy do tworzenia struktury drzewa i posiada takie właściwości jak:
Referencję do aktualnie zaznaczonego elementu w drzewie możemy pobrać za pomocą właściwości SelectedItem.


Menu, MenuItem i Separator
Wyświetla kontrolki typu MenuItem. Menu posiada właściwość IsMainMenu która po ustawieniu na True powoduje że naciśnięcie Alt + F10 ustawi aktywność na nim. Podstawowe właściwości MenuItem:
  • Command - komenda przypisana do danej pozycji menu
  • Header - Wyświetlany text w menu
  • Icon - ikona pozycji w menu
  • IsChecked - pokazuje zaznaczanie/odznaczenie po lewej stronie menu
  • Items - lista kontrolek MenuItem przypisanych do danej pozycji Menu
Aby dodać separator wystarczy użyć kontrolki Separator:


Code:
        <Menu>
            <MenuItem Header="_Plik">
                <MenuItem Header="Dodaj"/>
                <Separator/>
                <MenuItem Header="Zamknij"/>
            </MenuItem>
        </Menu>



ContextMenu
Menu kontekstowe skojarzone jest z konkretną kontrolką. Pojawia się po wciśnięciu prawego przycisku myszy bądź po naciśnięciu Shift+F10. Przykład definicji:


Code:
        <ListBox>
            <ListBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Wytnij" />
                    <MenuItem Header="Kopiuj" />
                    <MenuItem Header="Wklej" />
                </ContextMenu>
            </ListBox.ContextMenu>
        </ListBox>


ToolBar
Kontrolka świetnie nadająca się do umieszczania popularnych komend w postaci przycisków, check-boxów oraz labeli. Ważną właściwością jest ToolBar.OverflowMode, która decyduje w jaki sposób mają być wyświetlane kontrolki które się na nim nie mieszczą:
  • OverflowMode.Always - wyświetla z boku indykator, że są jeszcze inne polecenia do wyboru
  • OverflowMode.AsNeeded - wyświetla indykator tylko wtedy kiedy kontrolki faktycznie się nie mieszczą
  • OverflowMode.Never - dodatkowe komendy (które nie mieszczą się) nie będą dostępne
ToolBarTray - kontrolka ta umożliwia przemieszczanie toolbarów które się w niej znajdują.



StatusBar
Kontrolka używana w celu wyświetlania informacji o aktualnym stanie aplikacji (np. za pomocą Labela, ProgressBar itp)

70-511 Rozdział 1 - Tworzenie interfejsu użytwkownika - podstawowe kontrolki

Pierwszy rozdział treningu, dotyczy budowania interfejsu użytkownika. Platforma .NET umożliwia budowanie interfejsu użytkownika za pomocą WindowsForms lub WPF.
Budowa interfejsu w każdym z tych frameworków rządzi się swoimi prawami. My zajmiemy się WPFem.
Kontrolki w WPF można podzielić na 3 rodzaje:


  • Kontrolki indywidualne - spełniają najczęściej jedno zadanie: pozwalają na wprowadzenie tekstu (TextBox), wyświetlanie tekstu (Label, TextBlock), klikanie (Button) itp
  • Kontrolki przechowujące kolekcje obiektów - przechowują grupy powiązanych ze sobą obiektów - np. ListBox, Menu, TreeView
  • Kontrolki odpowiedzialne za rozmieszczenie innych kontrolek na formatce - np. Grid, StackPanel, Canvas

Content Controls
Kontrolka Content Control dziedziczy po klasie ContentControl i pozwala na zagnieżdżenie w sobie pojedynczej kontrolki. Zagnieżdżona kontrolka może być dowolnego typu, a odwołanie się do niej czy też jej przypisanie może nastąpić zarówno w kodzie jak i XAML za pomocą właściwości Content.
Właściwość Content jest typu object, tak więc można przypisać jej dowolny obiekt. Wyświetlenie takiej zagnieżdżonej kontrolki zależy od tego czy dziedziczy po klasie UIElement:
  • jeżeli nie dziedziczy po UIElement, zostanie zastosowana metoda ToString i jej rezultat będzie wyświetlony w kontrolce
  • jeżeli dziedziczy po UIElement, zostanie wyświetlona w taki sposób, jaki zostało to wyspecyfikowanie w kontrolce
Należy zauważyć, że pomimo tego, iż Content control, może zawierać tylko jeden zagnieżdżony element, za pomocą odpowiedniego kontenera (np. StackPanel) można wyświetlić więcej obiektów.


Label control - Mnemonic keys
Kontrolka ta wykorzystywana jest do wyświetlania tekstu. Kontrolka ta pozwala na korzystanie z tzw. mnemonic keys, czyli predefiniowanych skrótów, które definiują która kontrolka ma stać się aktywna w przypadku ich użycia.
Przykładowe użycie: Label oraz obok TextBox. Chcemy aby po naciśnięciu ALT + I został przeniesiony kursor na TextBox. Realizacja w kodzie:

Code:
            <Label Target="{Binding ElementName=tbFirstName}">Naciśnij Alt+_I</Label>
            <TextBox Name="tbFirstName" Height="30" Width="100" />

Mnemonic Key (skrót ustawiamy poprzez dodanie znaku podkreślenia "_" przed wybraną literą do skrótu. Kontrolkę docelową wskazujemy za pomocą bindowania i nazwy elementu na który wskazujemy.


Button control
Przycisk jest dobrze znaną kontrolkę więc nie będę się nad nim rozwodził.
Dwie ważne właściwości, które zwykle ustawiamy podczas tworzenia interfejsu użytkownika to:
  • IsDefault - determinuje, który klawisz zareaguje po naciśnięciu Entera na formatce
  • IsCanceled - determinuje który klawisz zareaguje po naciśnięciu klawisza Esc
Przyciski definiują także tzw. access keys (przyciski dostępu). Jest to funkcjonalność podobna do Mnemonic keys i w taki sam sposób jest definiowana (poprzez znak podkreślenia przed wybraną literą). Klawisz skrótu to także ALT + wybrana litera.


CheckBox
Pozwala na wybór opcji. Zawiera właściwość IsChecked która jest typu bool?. Przybiera więc 3 stany:
  • po otwarciu formatki: null
  • po zaznaczeniu: true
  • po odznaczeniu: false

RadioButton
RadioButton pozwala na wybór jednej opcji z wielu. Jeżeli chcemy pogrupować RadioButton-y mamy dwie możliwości:
  • w kontenerze (Grid, StackPanel) są one automatycznie grupowane do jednej grupy
  • Można użyć właściwości GroupName w celu przypisania RadioButtonowi innej grupy 

TextBlock
Kontrolka służąca do wyświetlania tekstu.


ImageControl
Kontrolka służąca do wyświetlania plików graficznych. Najważniejsze właściwości:
  • Source - źródło - tzw URI Uniform Resource Identifier - ścieżka do miejsca gdzie jest załadowana grafika
  • Stretch - format wyświetlania grafiki, do dyspozycji mamy jeden z czterech:
    • None - zawartość pliku graficznego jest wyświetlana w oryginalnym rozmiarze, w razie potrzeby przycinana jeżeli się nie zmieści w kontrolce
    • Fill - zawartość pliku graficznego jest powiększana/zmniejszana w celu dopasowania do powierzchni w kontrolce ImageControl
    • Uniform - dostosowanie wielkości grafiki do kontrolki z proporcji obrazu
    • UniformToFill - plik graficzny jest odpowiednio powiększany/zmniejszany aby dopasować się do wielkości kontrolki. Zostają zachowane proporcje obrazu, w razie nie zmieszczenia obrazu zostaje on obcięty.

TextBox
Kontrolka umożliwia użytkownikowi wprowadzanie teksu. Najważniejsze właściwości:
  • IsReadOnly - tylko do odczytu
  • TextWrapping - umożliwia wprowadzanie wielu linii tekstu po ustawieniu tej właściwości na "Wrap"
  • VerticalScrollBarVisibility - dodaje pasek przewijania z góry na dół w kontrolce

ProgressBar
Daje możliwość wizualnego przedstawienia użytkownikowi postępu podczas wykonywania czasochłonnych operacji. Podstawowe właściwości:
  • IsIndeterminate - jeżeli ustawione na False pasek postępu wyświetla wartość z pola Value, w przeciwnym przypadku pasek postępu będzie "krążył" nie oddając do końca obecnego postępu
  • Maximum - maksymalna wartość właściwości Value (oznacza 100%)
  • Minimum - minimalna wartość Value (oznacza 0%)
  • Orientation - położne paska postępu pionowe lub poziome
  • Value - aktualna wartość postępu

Slider
Pozwana użytkownikowi w graficzny sposób zmienić wartość. Podstawowe właściwości:
  • IsDirectionReversed - determinuje czy kierunek jest odwrócony (od prawa do lewa)
  • LargeChange - maksymalna zmiana w przypadku kliknięcia myszką na końcu paska
  • Orientation - orientacja (pozioma lub pionowa)
  • SmallChange - najmniejsza zmiana w przypadku kliknięcia myszką na pasku
  • TickFrequency - determinuje podziałkę (co ile ma być)
  • TickPlacement - położenie podziałki
  • Ticks - ręczne przypisanie wartości podziałki i położenia
  • Value - aktualna wartość

Kolejność przechodzenia po kontrolkach za pomocą klawisza TAB
  • Ustawiamy za pomocą właściwości TabIndex
  • Kontrolki które nie mają zdefiniowanej wartości TabIndex otrzymują aktywność po przejściu wszystkich kontrolek, które mają ją ustawioną
  • Jeżeli kontrolki maja ustawiony ten sam TabIndex, kolejność przejścia jest determinowana kolejnością zadeklarowania w XAML-u
Jeżeli nie chcemy aby któraś kontrolka otrzymała aktywność podczas używania klawisza TAB, należy ustawić właściwość KeyboardNavigation.IsTabStop na False 

poniedziałek, 23 kwietnia 2012

Egzamin 70-511 / 72-511

W najbliższym czasie zamierzam zdać egzamin MCTS 70-511 (lub jego odpowiednik 72-511 wersja studencka o połowę tańsza jeżeli ktoś jest jeszcze studentem).

Egzamin ten dotyczy Tworzenia aplikacji desktopowych z wykorzystaniem .NET 4.0
Egzamin ten zawiera pytania z takich obszarów projektowania aplikacji jak:
  1. Tworzenie prostego interfejsu użytkownika
    • Selekcja kontrolki najbardziej dopasowanej do wymagań danego zadania
    • Tworzenie hierarchicznego układu kontrolek na formatce (użycie różnorakich kontrolek pozwalających na ustawienie pozycji kontrolek)
    • Tworzenie i używanie stylów oraz skórek
    • Zarządzanie reużywalnymi zasobami (czcionki, style, źródła danych, obrazki)
    • Animacja w WPF (tworzenie storyboard, kontrola linii czasu, kontrola animacji za pomocą kodu i XAML)
  2. Udoskonalanie interfejsu użytkownika przy zastosowaniu zaawansowanych technik:
    • Routet events
    • Komendy (commands)
    • Modyfikacja interfejsu użytkownika w czasie działania programu (dodawanie/usuwanie kontrolek w czasie działania programu, dynamiczne generowanie szablonu)
    • Definiowanie własnych kontrolek
    • Tworzenie i wyświetlanie grafiki - bez uwzględnienia grafiki trójwymiarowej (3D)
    • Multimedia w aplikacji WPF
    • Szablony kontrolek w WPF
    • Tworzenie triggerów
  3. Zarządzanie danymi w warstwie prezentacji
    • Bindowanie danych do kontrolek
    • Tworzenie konwerterów danych (Value Converter)
    • Implementacja walidacji danych
    • Implementacja powiadamiania o zmianie danych
    • Przygotowanie kolekcji danych do wyświetlenia (filtrowanie, grupowanie, sortowanie, LINQ)
    • Bindowanie do hierarchicznych źródeł danych
    • Implementacja wyświetlania danych w DataGrid
    • Tworzenie szablonu wyświetlania danych
  4.  Poprawa i używalności aplikacji desktopowych
    • Integracja WPF i WindowsForms (ControlHosts, PropertyMap)
    • Implementacja wielowątkowości (TPL, parallel LINQ itp)
    • Globalizacja 
    • Drag & Drop
    • Bezpieczeństwo (SRP, CAS policy, UAC)
    • Zarządzanie ustawieniami użytkownika
    • Dependency propeteries
  5. Wydanie produktu
    • Testowanie aplikacji WPF
    • Debugowanie XAML przy użyciu WPF Visualizer
    • Wyszukiwanie błędów przy użyciu PresentationTraceSources
    • Konfiguracja wydania ClickOnce  
    • Tworzenie instalatora do aplikacji
    • Konfiguracja ustawień bezpieczeństwa wydania. 

Tak wygląda w skrócie plan nauki do egzamin 70-511 / 72-511. Materiały z których będę czerpać wiedzę, to przede wszystkim Training Kit 70-511, MSDN oraz inne książki przeznaczone do nauki WPF. 

sobota, 21 kwietnia 2012

LINQ Join Extension method

Zobaczmy na prosty model EF:






Standardowo chcąc wyciągnąć imię, nazwisko i miasto w którym mieszka klient, używamy SQL-o podobnej składni LINQ:


Code:
                var q = from c in contex.Customers
                        join ca in contex.CustomerAddresses on c.CustomerID equals ca.CustomerID
                        join a in contex.Addresses on ca.AddressID equals a.AddressID
                        select new{Customer = c, Address = a};

Takie zapytanie możemy przerobić do zapytania z wykorzystaniem Extension methods:


Code:
                var q2 = contex.Customers.Join(contex.CustomerAddresses, c => c.CustomerID, ca => ca.CustomerID,
                                               (c, ca) => new{Customer = c, CustomerAddress = ca})
                    .Join(contex.Addresses, ca => ca.CustomerAddress.AddressID, a => a.AddressID,
                          (ca, a) => new{ca.Customer, Address = a});

O ile pierwszy sposób jest bardzo czytelny, o tyle drugi może na pierwszy rzut oka wydawać się skomplikowany. Zwłaszcza metoda Join jest tutaj rozbudowana. Zobaczmy na jej budowę:


Code:
public static IQueryable<TResult> Join<TOuter,TInner,TKey,TResult>
(this IQueryable<TOuter> outer, 
IEnumerable<TInner> inner, 
Expression<Func<TOuter,TKey>> outerKeySelector, 
Expression<Func<TInner,TKey>> innerKeySelector, 
Expression<Func<TOuter,TInner,TResult>> resultSelector)

elementy które podajemy w tej metodzie:
  • outer - Extension method więc typ który jest przekazywany niejawnie (on nas nie interesuje na ten moment)
  • inner - źródło z którym nastąpi złączenie (w naszym przypadku była to tabela CustomerAddresses)
  • outerKeySelector oraz innerKeySelektor - dwa wyrażenia lambda, które definiują warunek złączenia (np. my łączymy po polu AddressId)
  • resultSelector - typ zwracany czyli odpowiednik select dla składni SQL-o podobnej


Code:
.Join
(źródło z którym łączymy, 
właściwość na podstawie której łaczymy zewnętrzna tabela, 
właściwość na podstawie której łaczymy wewnętrzna tabela, 
rezultat)

czwartek, 12 kwietnia 2012

Chroniony konstruktor w klasie abstrakcyjnej

Problem typu "the best design". Mamy klasę abstrakcyjną:

Code:
    public abstract class Connection
    {
        protected DbConnection DbConnection;

        public Connection(DbConnection dbConnection)
        {
            DbConnection = dbConnection;
        }
    }

Czy jest to poprawny kod? Tak jest z punktu widzenia kompilatora jest to całkowicie poprawny kod. Obiektu klasy abstrakcyjnej nie da się utworzyć. Tak więc w wielu źródłach można znaleźć informację, aby konstruktor uczynić chroniony - w końcu i tak bezpośrednio z niego nie skorzystamy.
Lepsza definicja klasy będzie mieć więc następującą postać:

Code:
    public abstract class Connection
    {
        protected DbConnection DbConnection;

        protected Connection(DbConnection dbConnection)
        {
            DbConnection = dbConnection;
        }
    }

poniedziałek, 9 kwietnia 2012

Sprawdzenie czy login został już zajęty - atrybut Remote

W ASP.MVC 3 wykorzystano tzw. Unobtrusive JavaScript. W skrócie jest zbiór zasad, jak budować strony z wykorzystaniem JavaScript.

Mój scenariusz przewiduje tworzenie konta użytkownika. W bazie danych login jest polem unikalnym, co znaczy że nie może być dwóch użytkowników o takim samym loginie, czy też takim samym mailem. Standardowo walidacja przeprowadzana jest na serwerze, chciałem także, aby użytkownik został od razu poinformowany podczas wprowadzania loginu że jest on zajęty.
W MVC 3 jest to niezwykle proste.
Na początek w modelu, dodaję do właściwości UserName dodaję atrybut Remote:

Code:
        [Required]
        [Display(Name = "Nazwa użytkownika")]
        [Remote("IsUserExistInDatabase", "Account", HttpMethod = "POST", ErrorMessage = "Taki użytkownik już istnieje. Proszę wybrać inny login.")]
        public string UserName { get; set; }

Elementami składowymi są kolejno:
  • IsUserExistInDatabase - nazwa metody (akcji) która zostanie wywołana podczas walidacji
  • Account - nazwa kontrolera w którym akcja walidacji się znajduje
  • HttpMethod - w jaki sposób ma zostać wysłane zapytanie do kontrolera
  • ErrorMessage - komunikat błędu który ma zostać wyświetlony użytkownikowi w przypadku gdy walidacja nie przejdzie pomyślnie
Następnie w widoku dodajemy odnośniki do skryptów z walidacją:

Code:
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

Teraz pozostaje jeszcze ustalić w którym miejscu widoku ma zostać wyświetlony komunikat z błędem odnośnie loginu:

Code:
@Html.ValidationMessageFor(x => x.UserName)

Ostatnia czynność to napisanie metody w wskazanym kontrolerze, która jako parametr przyjmuje wartość naszego pola, a jako rezultat zwraca Json:

Code:
        [HttpPost]
        public JsonResult IsUserExistInDatabase(string username)
        {
            var user = Membership.GetUser(username);

            return Json(user == null);
        }

Ot tyle, aby uzyskać walidację istnienia loginu.