Inżynieria Programowania - Lab5

Transkrypt

Inżynieria Programowania - Lab5
Inżynieria Programowania
Laboratorium 5
Część Wizualna
Paweł Paduch [email protected]
11-05-2013
Rozdział 1
Wstęp
Na dzisiejszych zajęciach poznamy jeden ze sposobów tworzenia okienkowej aplikacji w środowisku Visual Studio 2010 wykorzystując WPF (Windows
Presentation Foundation. Oczywiście najpełniejszym źródłem wiedzy jest dokumentacja ze stron twórcy.
http://msdn.microsoft.com/en-us/library/ms754130(v=vs.100).aspx
WPF w porównaniu do klasycznego API Windows Form ma o wiele większe
możliwości. Łączy w sobie kilka technologii. Poza klasycznym używaniem formatek z kontrolkami, można tworzyć grafiki 2D (tak jak w przypadku GDI+
System.Drawing.dll), obsługa grafiki 3D (wcześniej API DirectX), odtwarzanie
strumieni wideo (wcześniej API Windows Media Player), oraz zarządzanie przepływem dokumentów. Wszystkie te technologie zostały zunifikowane do wspólnego API pod nazwą WPF. Celem dzisiejszych zajęć jest poznanie podstaw
WPF. Dowiemy się jak stworzyć i skonfigurować proste okienko. Dodać kontrolki menu, okienka wprowadzania tekstu, guziki i tabelki. A co najważniejsze,
będziemy operować na naszej bazie danych za pomocą wcześniej przygotowanej
biblioteki RezerwacjeLib.
1
Rozdział 2
Na początek
Na ostatnich zajęciach stworzyliśmy, bibliotekę dostępu do bazy danych. Posłuży nam ona za warstwę połączeniową. To z jej obiektów i metod będziemy
korzystać gdy będziemy chcieli pobrać, dodać czy usunąć rekordy. Zanim jednak
przejdziemy do tworzenia aplikacji wprowadzimy jeszcze kilka zmian w RezerwacjeLib.
2.1
Nazewnictwo
Ostatnio problemem okazały się niezbyt trafnie dobrane nazwy np. musieliśmy tworzyć klasę Uzytkownicy, która operowała na tablicy Osoby. (klasa Osoby
jest automatycznie generowane przez Entity Framework), mieliśmy Role zamiast
Uprawnień itp. Poza tym w bazie nazwy tablic zwykle określały liczbę mnogą
elementów w nich trzymanych (np. Osoby. Tytuly itd.) a np. Rezerwacja już
nie. Kolejny problem do duże i małe litery, niektórzy stosowali małe litery w nazwach tabel to z kolei wprost przekładało się na nazwy klas wygenerowanych
przez EF. Aby jednoznacznie i w sposób zunifikowany zrobić porządek z nazwami proponuję następującą nomenklaturę tabel w bazie:
• DniKalendarzaAkademickiego
• KalendarzeAkademickie
• Osoby
• Propozycje
• PropozycjeRezerwacje
• PrzedzialyCzasowe
• Rezerwacje
• RezerwacjeOsoby
• SchematyGodzinowe
• StanyRezerwacji
2
• TypyRezerwacji
• TypyZasobow (nowa tabelka)
• Tytuly
• Uprawnienia
• Wiadomosci
• Zasoby
Dojdzie też jedna tabelka 2.1TypyZasobow: Do tablicy Zasoby dodamy też pole
IdTypuZasobu
Typ
tinyint
varchar(50)
Tabela 2.1: Typy zasobów
IdTypuZasobu będące kluczem obcym i mającym zależność z tabeleką TypyZasobow. Oczywiście pamiętamy by IdTypuZasobu w TypyZasobow ustawić jako
klucz główny oraz Indentity. Po tych zmianach zapisujemy wszystko i robimy aktualizację modelu Rezerwacje.edmx w RezerwacjeLib. Tabele z nowymi nazwami
zostaną naniesione, niestety stare tabele zostaną powodując błędy w stylu:
Error 7 Error 11007: Entity type ’KalendarzAkademicki’ is not mapped. Tabelki powodujące błędy należy usunąć oraz jeszcze raz zaktualizować model. Gdy
nie ma już błędów w modelu należy przebudować bibliotekę i poprawić nazwy
w plikach *.cs.
Kolejne problemy z nazwami to nazwy klas wygenerowanych przez EF oraz
klas napisanych przez nas w celu obsłużenia wskazanych tabel.1 Można je rozróżnić dodając jakiś prefiks lub sufiks (np. Class). Jednak jeszcze lepszą metodą
będzie skorzystanie z faktu, że klasy generowane przez EF są klasami częściowymi (ang. partial). Proszę sobie przejrzeć plik RezerwacjeDesigner.cs. W pliku
tym nie możemy dodawać nowych metod. W ogóle nie powinniśmy tam nic
zmieniać, bo po aktualizacji plik jako generowany automatycznie zostanie nadpisany. Możemy jednak wygenerowane klasy rozszerzyć o nową funkcjonalność
w swoich plikach. Zanim to zrobimy uporządkujmy sobie nazewnictwo naszych
plików podając nazwy takie jak w bazie np. Osoby.cs, Rezerwacje.cs itd. Najlepiej to zrobić zmieniając nazwę plików *.cs w solution explorerze potwierdzając
propozycję zamiany nazewnictwa w reszcie projektu. Następnie zmieniając nazwy klas (już w pliku) podajemy przy okazji kwalifikator partial (bez tego słowa
kluczowego będą zgłaszane błędy, że klasa o podanej nazwie istnieje). Tak jak
to jest w listingu 2.1.
2.2
ści:
Podstawowe metody
W dzisiejszym programie będziemy potrzebowali następującej funkcjonalno-
1 Istnieje jeszcze jedna metoda, mapowania nazw. Gdy w modelu wygenerowanym z bazy
(plik *.edmx) wybierzemy z menu kontekstowego danej klasy Table Mapping możemy dostosować nazewnictwo wygenerowane automatycznie do nazwenictwa dla nas odpowiedniego.
3
• pobieranie zbioru wszystkich obiektów danego typu np. Tytułów
IQueryable<Tytuly> getAll()
• dodawanie pojedynczego obiektu danego typu np. void dodaj(Tytuly tytul)
• usuwanie podanego obiektu np. void usun(Tytuly tytul)
• nanoszenie stanu kontekstu do bazy void zapisz()
Przykładowo dla listy tytułów podstawowa klasa Tytul powinna zawierać metody jak na listingu 2.1 Nie oznacza to, że jeżeli mieliśmy już jakieś inne funkcje
(np. wyszukaj tytuł po id) mamy je usuwać.
Listing 2.1: Klasa Tytuly.cs
1
2
3
4
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
5
6
7
8
9
10
namespace RezerwacjeLib
{
public partial class Tytuly
{
private rezerwacjeEntities context = new rezerwacjeEntities();
11
public IQueryable<Tytuly> getAll()
{
return from wybrane in context.Tytuly select wybrane;
}
12
13
14
15
16
public void dodaj(Tytuly tytul)
{
context.Tytuly.AddObject(tytul);
}
17
18
19
20
21
public void usun(Tytuly tytul)
{
context.Tytuly.DeleteObject(tytul);
}
22
23
24
25
26
public void zapisz()
{
context.SaveChanges();
}
27
28
29
30
}
31
32
}
Powinniśmy zaimplementować powyższe metody do klas:
• Zasoby,
• Uprawnienia,
• Tytuly,
• StanyRez,
• TypyRez
• oraz TypyZasobow.
Dodatkowo z poprzednich zajęć powinniśmy mieć funkcję znajdująca po loginie
i haśle jak w listingu 2.2
4
Listing 2.2: Szukaj po loginie i haśle
1
2
3
4
5
public Osoby znajdzOsobePoLoginieIHasle(string login, string haslo)
{
var osoby = (from os in context.Osoby where os.Login == login && os.Haslo == ←haslo select os).FirstOrDefault();
return osoby;
}
Przyda nam się też funkcja zwracająca wszystkie osoby. Można napisać nową podobnie jak w listingu 2.1 lub wykorzystać np. funkcję, która szuka po
nazwisku z maską i podać gwiazdkę aby wyszukała wszystkie wystąpienia.
Reszta nie będzie nam dziś potrzebna choć dla pełnej obsługi można zrobić.
Przypominam bibliotekę przebudowujemy za pomocą klawisza F6.
5
Rozdział 3
Nowy projekt
Z górnego menu wybieramy: File→New Project.
W okienku wyboru nowego projektu zaznaczamy Visual C#→Windows WPF
Application. Na dole wpisujemy nazwę projektu RezerwacjeApp i potwierdzamy
OK. (rys. 3.1)
Rysunek 3.1: Okienko wybierania nowego projektu.
Otworzy nam się pierwsze domyślne okno główne, pod spodem (jeżeli nie
ma to włączyć w menu view) mamy kod XAML. Jest to plik xmlowy opisujący
wygląd naszego okna. Aplikację WPF można stworzyć na 3 sposoby.
• W czystym XAML’u wtedy odpowiedni kod jest zawarty w tagach <x:code>,
• w czystmy C# bez XAML, wtedy właściwości poszczególnych elementów
przypisujemy z kodu
• oraz najpopularniejszy i sugerowany sposób tzw. Code-Behind. Część wizualna - zachowanie interfejsu użytkownika to kod XAML natomiast oprogramowanie zdarzeń w kodzie C#.
6
My będziemy tworzyć aplikację według tego trzeciego sposobu.
Większość właściwości można „wyklikać” zarówno w samym oknie pokazującym
przykładowy wygląd jak i w okienku Properties. Np, sposób wyrównywania, kolory, podpięte eventy.
Jak ktoś chce można edytować plik XAML i obserwować efekty w oknie podglądu. Są też dodatkowe programy do edycji XAML jak chociażby Expression
Blend.
Zmieńmy tytuł okna na Rezerwacje (niezalogowany). Można też pobawić się
kolorami, np. dać tło w postaci cieniowanej.
Zanim przejdziemy dalej, pamiętajmy aby dodać referencje do naszej biblioteki (RezerwacjeLib), System.Data.Entity oraz dodać plik konfiguracji, w którym jest między innymi opis połączenia z bazą (App.config). W każdym nowym pliku *.cs dodajemy też informację o używanej przestrzeni nazw using
RezerwacjeLib;. Jednym z takich plików jest automatycznie stworzony MainWindow.xaml.cs w którym zawarta jest logika działania okna MainWindow.
Identycznie jak robiliśmy w przypadku aplikacji konsolowej na poprzednich zajęciach.
3.1
Menu
Na początek dodajmy proste menu. Pod tagiem <Grid> umieszczamy kod
jak na listingu 3.1
Listing 3.1: Menu w MainWindow.xaml
1
2
3
4
5
6
7
8
9
10
11
12
<Menu HorizontalAlignment="Left" Name="menuGlowne">
<MenuItem Header="Zaloguj" Name="Logowanie" Click="Logowanie_Click"/>
<MenuItem Header="Osoby" Name="Osoby" Click="Osoby_Click"/>
<MenuItem Header="Słowniki" Name="Slowniki" Click="Slowniki_Click">
<MenuItem Header="Zasoby" Name="Zasoby" Click="Zasoby_Click"/>
<MenuItem Header="Typy Zasobów" Name="TypyZasobow" Click="TypyZasobow_Click"/←>
<MenuItem Header="Typy Rezerwacji" Name="TypyRezerwacji" Click="←TypyRezerwacji_Click"/>
<MenuItem Header="Stany Rezerwacji" Name="StanyRezerwacji" Click="←StanyRezerwacji_Click"/>
<MenuItem Header="Tytuły" Name="Tytuly" Click="Tytuly_Click"/>
<MenuItem Header="Uprawnienia" Name="Uprawnienia" Click="Uprawnienia_Click"/>
</MenuItem>
</Menu>
Wartość atrybutu Click to nazwa funkcji wywoływanej do obsługi kliknięcia w
dany element menu. Z menu Properties wybieramy zakładkę Events i odnajdujemy zdarzenie Click. Powinna być tam już wpisana nazwa naszej metody.
Tylko gdzie jest jej implementacja? Jeszcze nie ma ale do czasu. Teraz wystarczy kliknąć dwukrotnie tę nazwę. Otworzny nam się plik MainWindow.xaml.cs
a kursor ustawi na nowo wygenerowanym szkielecie funkcji obsługującej zdarzenie kliknięcia. Tak należy postąpić ze wszystkimi funkcjami. Gdy wszystko jest
już poprawione powinniśmy móc skompilować (F5).
7
Rozdział 4
Logowanie
Pierwszą, czynnością w naszym programie będzie zalogowanie się do systemu. Logowanie będzie bardzo prymitywne. Poprosimy użytkownika o podanie
loginu i hasła. Program za pomocą wcześniej stworzonej metody znajdzOsobePoLoginieIHasle odszuka użytkownika w bazie. Jeżeli takiego nie znajdzie uruchomi nam się aplikacja w trybie niezalogowany. Na chwilę obecną nie będziemy
rozróżniać uprawnień i poza wpisem w tytule okienka nie będzie żadnej różnicy pomiędzy użytkownikami. Jednak jesteśmy gotowi do rozpoznania według
jakiego schematu uprawnień program ma działać.
4.1
Okno logowania
Z menu Solution Explorer wybieramy Add→Window. Nadajemy nazwę
WinLogowanie. Do okienka dodajemy dwie kontrolki typu Label jednką TextBox,
jedną PasswordBox oraz dwie typu Button Etykietki to napisy odpowiednio
„Login” i „Hasło”. Guziki to „Zaloguj” i „Anuluj”. Pola do wprowadzania tekstu
powinny mieć nazwy passwordBoxHaslo oraz textBoxLogin. Guziki nazywamy
buttonZaloguj i buttonAnuluj. Mniej więcej jak na rys. 4.1
4.2
Obsługa Logowania
W obrębie bieżącej przestrzeni nazw (np. tworząc osobny plik Enumeracje.cs) tworzymy enumerację jak na 4.1 Tworzymy też nowy typ danych reprezentujący wiersz wyszukanych osób. (to nam się przyda nieco dalej).
Listing 4.1: Stany logowania
1
2
3
4
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
5
6
7
8
9
10
11
namespace Rezerwacje
{
public enum LoginResult
{
Canceled,LoginOk,BadLogin
}
8
Rysunek 4.1: Projekt okienka logowania .
12
public class WierszOsoby
{
public long IdOsoby { get; set; }
public string Tytul { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Login { get; set; }
}
13
14
15
16
17
18
19
20
21
class Enumeracje
{
}
22
23
24
25
}
Do pliku WinLogowanie.xaml.cs dodajemy zmienne określające jak przebiegło logowanie (listing 4.2
Listing 4.2: Zmienne w WinLogowanie.xaml.cs
1
2
3
4
5
6
public Osoby zalogowanaOsoba = null;
private LoginResult lr; // rezultat logowania
public LoginResult loginResult //ale tylko do odczytu
{
get { return lr; }
}
Podpinamy też obsługę zdarzeń po kliknięciu guzików Zaloguj oraz Anuluj. jak
na listingach 4.3 oraz 4.4
Listing 4.3: Zaloguj WinLogowanie.xaml.cs
1
2
3
4
5
6
7
private void buttonLoguj_Click(object sender, RoutedEventArgs e)
{
Osoby users = new Osoby();
zalogowanaOsoba = users.znajdzOsobePoLoginieIHasle(this.textBoxLogin.Text, this.←passwordBoxHaslo.Password);
if (zalogowanaOsoba != null)
{
lr = LoginResult.LoginOk;
9
}
else
{
lr = LoginResult.BadLogin;
}
this.Close();
8
9
10
11
12
13
14
}
Listing 4.4: Anuluj WinLogowanie.xaml.cs
1
2
3
4
5
6
private void buttonWyjdz_Click(object sender, RoutedEventArgs e)
{
zalogowanaOsoba = null;
lr = LoginResult.Canceled;
this.Close();
}
Teraz jeszcze tylko pozostaje obsłużyć logowanie w MainWindow.xaml.cs.
Potrzebne będą nam 3 funkcje:
• Zaloguj
• Wyloguj
• oraz obsługa kliknięcia w menu.
Przechodzimy do pliku MainWindow.xaml.cs W klasie MainWindow dodajmy zmienną private Osoby zalogowany = null; Dodajemy funkcję „Zaloguj” jak
w listingu 4.5.
Listing 4.5: Zaloguj w MainWindow.xaml.cs
1
2
3
4
private Osoby zaloguj()
{
WinLogowanie winlogin = new WinLogowanie();
winlogin.ShowDialog();
5
Osoby ret = winlogin.zalogowanaOsoba;
switch (winlogin.loginResult)
{
case LoginResult.LoginOk:
if (ret != null)
{
this.Title = "Rezerwacje (zalogowany " + ret.Imie + " " + ret.←Nazwisko + " <" + ret.Uprawnienia.Nazwa + "> )";
this.Logowanie.Header = "Wyloguj";
}
else
{
MessageBox.Show("Dziwne Osoba == null choć login ok");
throw new Exception("Osoba == null choć została znaleziona");
}
break;
case LoginResult.BadLogin:
MessageBox.Show("Nieprawidłowe logowanie");
break;
case LoginResult.Canceled:
break;
default:
throw new Exception("Nieobsłużony case");
}
return ret;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
}
10
Tworzy ona nowy obiekty typu WinLogowanie oraz wyświetla go jako dialog (czyli czeka na zamknięcie). Następnie odczytuje co zwróciło okienko, jeżeli użytkownik został znaleziony dostaniemy jego instancję oraz potwierdzenie
poprawnego logowania, w przypadku niepowodzenia lub anulowania zalogowanaOsoba będzie miała wartość null. Na tej podstawie możemy określić różne
zachowania. Np. można ustawić tytuł głównego okna z informacją o zalogowanej osobie, oraz zmienić napis na przycisku logowania w głównym menu.
Wylogowanie będzie dużo prostsze (listing 4.6). Działanie wylogowania wprowadza tylko zmiany kosmetyczne, ale w przyszłości można jeszcze zawrzeć np.
zatwierdzenie wykonanych zmian lub pytanie czy na pewno wylogować.
Listing 4.6: Wylogowanie w MainWindow.xaml.cs
1
2
3
4
5
6
private void wyloguj()
{
zalogowany = null;
this.Logowanie.Header = "Zaloguj";
this.Title = "Rezerwacje (niezalogowany)";
}
Odszukujemy wygenerowaną funkcję Logowanie Click i implementujemy kod
jak na listingu 4.7
Listing 4.7: Obsługa Logowanie Click w MainWindow.xaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
private void Logowanie_Click(object sender, RoutedEventArgs e)
{
if (zalogowany == null) //jak nie zalogowani to się logujemy
{
if ((zalogowany = zaloguj()) != null)
{
//miejsce na dodatkowe czynności wiedząc kto się zalogował
}
}
else //jak zalogowani to się wylogujemy
wyloguj();
}
Kolejną modyfikacją jaką można dokonać jest automatyczne utworzenie okna
logowania przy załadowaniu okna głównego. W tym celu należy w oknie głównym obsłużyć zdarzenie Loaded jak na listingu 4.8.
Listing 4.8: Obsługa Window Loaded w MainWindow.xaml.cs
1
2
3
4
private void Window_Loaded(object sender, RoutedEventArgs e)
{
zalogowany = zaloguj();
}
Żeby jeszcze bardziej ułatwić użytkownikowi logowanie, można ustawić kursor w okienku do wprowadzania loginu. W tym celu należy w konstruktorze
WinLogowanie wywołać metodę Focus() na obiekcie textBoxLogin. Jeżeli uda
nam się skompilować i uruchomić naszą aplikację, powinniśmy na wstępie dostać
okienko logowania. Po zalogowaniu powinniśmy mieć możliwość wylogowania
oraz zalogowania ponownego. W przypadku błędu związanego z połączeniem,
sprawdzić czy nie zapomnieliśmy o pliku App.config.
11
Rozdział 5
Edycja danych w prostych
tabelach
Do tej pory operacje na bazie były dość ograniczone. Jedynie jedno zapytanie
o użytkownika. Nie wymagało to specjalnych konstrukcji do przeglądania danych
lub ich poprawiania czy dodawania. Chcąc operować na większej liczbie danych
posłużymy się tabelką. Na początku będzie to tabelka, w której umieścimy
odczytane dane.
Scenariusz będzie następujący:
• Klikam w menu Słowniki→Tytuły
• Wywoływana jest procedura obsługi kliknięcia Tytuly Click
• Otwierane jest nowe okienko z tabelką
• Tabelka jest wypełniana danymi z bazy
• Zamykam okno.
Zacznijmy od utworzenia nowego okna WinTytuly. Nadajmy mu tytuł „Tytuły”.
Dodajmy nowe źródło danych. Z lewej strony z paska narzędzi należy wybrać
zakładkę Data Sources. Gdy nie dodawaliśmy wcześniej żadnego źródła danych
zobaczymy tylko puste miejsce z informacją aby takie źródło dodać. Klikamy
w Add New Data Source... wyskoczy nam okienko kreatora dodawania nowego
źródła danych. (rys. 5.1).
Wybieramy Object klikamy dalej. W kolejnym kroku (Rys. 5.2) wybieramy
RezerwacjeLib.
Teraz wystarczy przeciągnąć nazwę interesującej nas tabelki na nowe okno.
Powstanie element DataGrid wraz ze zdefiniowanymi kolumnami. Tabelkę i okno
musimy nieco dopasować by jedno w drugim się mieściło.
Teraz należałoby wyświetlić okienko po naciśnięciu odpowiedniego elementu
z menu. W tym celu wypełniamy funkcję Tytuly Click jak na listingu 5.1.
Listing 5.1: Obsługa Tytuly Click w MainWindow.xaml.cs
1
2
private void Tytuly_Click(object sender, RoutedEventArgs e)
{
12
Rysunek 5.1: Dodawanie nowego źródła danych.
Rysunek 5.2: Dodawanie nowego źródła danych.
13
WinTytuly oknoTytulow = new WinTytuly();
oknoTytulow.Show();
3
4
5
}
Po skompilowaniu i uruchomieniu powinniśmy móc zobaczyć okno z tabelką. Niestety tabelka jeszcze jest pusta. Należy teraz wypełnić ją danymi. Na
szczęście jest to kwestia dopisania trzech linijek kodu. Otwieramy plik WinTytuly.xaml.cs. Pamiętamy by dopisać using RezerwacjeLib;.
Odszukujemy wygenerowaną funkcję Window Loaded i dodajemy zmienną tytuly
oraz modyfikujemy ostatnią linijkę jak to jest pokazane w przykładzie 5.2.
Listing 5.2: Zmiany w WinTytuly.xaml.cs
1
2
3
4
5
6
7
Tytuly tytuly = new Tytuly();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource tytulyViewSource = ((System.Windows.Data←.CollectionViewSource)(this.FindResource("tytulyViewSource")));
// Load data by setting the CollectionViewSource.Source property:
tytulyViewSource.Source = tytuly.getAll();
}
Widzimy, że po pierwsze stworzyliśmy sobie obiekt klasy Tytuly (to w nim zaimplementowaliśmy metodę zwracającą wszystkie rekordy getAll()). Następnie
ustalamy, że źródłem danych jest lista obiektów znalezionych przez metodę getAll(). Ponownie skompilujmy i zobaczmy wygląd nowego okna z tytułami.
Pozostaje nam zaimplementować obłsugę edycji danych. W okienku WinTytuly dodajemy dwa guziki Zapisz i Wyjdź. Oprogramujemy je dwoma poleceniami (tak tylko dwoma :) ).
tytuly.zapisz();
Close();
5.1
Pierwsze samodzielne zadanie
Po tym dość długim tutorialu, czas na pierwsze samodzielne zadanie. Oprogramuj tak jak w przykładzie edycje dla tabel:
• TypyZasobow
• StanyRez
• TypyRez
• Uprawnienia
Tabelka z zasobami jest nieco trudniejsza dlatego zajmiemy się nią w osobnym
rozdziale.
14
Rozdział 6
Kolumna z polami
ComboBox
Ponieważ w tabeli Zasoby jest pole IdTypuZasobu będące kluczem obcym do
tabelki TypyZasobow tę kolumnę potraktujemy specjalnie. Użyjemy kontrolki
typu ComboBox z możliwością wybrania typu zasobu dla danego wiersza. Tak
jak na rysunku 6.1.
Rysunek 6.1: Przykładowe okno zasobów.
W polu typu Combo mamy słownik, w którym określamy, które pole będzie
wyświetlane (Typ) oraz za pomocą którego pola powiążemy słownik z zasobami
(IdTypuZasobu). Definicja kolumny będzie wyglądać jak na listingu 6.1.
Listing 6.1: Zastosowanie pola ComboBox w tabelce
1
<DataGridComboBoxColumn x:Name="combo"
15
2
3
4
5
6
7
8
Header="Typ"
Width="Auto"
CanUserSort="True"
SortMemberPath="TypyZasobow.Typ"
DisplayMemberPath="Typ"
SelectedValueBinding="{Binding Path=IdTypuZasobu}"
SelectedValuePath="IdTypuZasobu"/>
Dodatkowo aby wypełnić kontrolkę ComboBox danymi trzeba w pliku WinZasoby.xaml.cs dodać ładowanie typów zasobów. Czyli najpierw stworzyć obiekt
typu TypyZasobow następnie za jego pomocą wypełnić combo.ItemsSource jak
w listingu 6.2 w linii 8. Konwersja ToList jest potrzebna, aby umożliwić użytkownikowi sortowanie po wybranych kolumnach.
Listing 6.2: Załaduj typy zasobów
1
2
3
4
5
6
7
8
9
Zasoby zasoby = new Zasoby();
TypyZasobow typyZasobow = new TypyZasobow();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource zasobyViewSource = ((System.Windows.Data←.CollectionViewSource)(this.FindResource("zasobyViewSource")));
// Load data by setting the CollectionViewSource.Source property:
zasobyViewSource.Source = zasoby.getAll().ToList(); //Listę da się sortować
combo.ItemsSource = typyZasobow.getAll().ToList();
}
16
Rozdział 7
Punktacja
Praca na zajęciach oceniana będzie następująco:
• Uporanie się z nazewnictwem 0,5 pkt.
• Stworzenie/uzupełnienie podstawowych metod 0,5 pkt.
• Stworzenie nowego projektu wraz z menu 0.5 pkt.
• Zaimplementowanie okna logowania 1 pkt.
• Zaimplementowanie edycji tytułów, (według tutoriala) 0,5 pkt.
• Zaimplementowanie obsługi reszty tablic słownikowych z punktu 5.1 1,5
pkt.
• Zaimplementować obsługę tabelki Zasoby według przykładu podanego w
punkcie 6 0,5 pkt.
Proszę zachować kolejność wykonywania poszczególnych zadań. Pominięcie niektórych etapów może skutkować brakiem możliwości wykonania kolejnych punktów. Ocenie będą podlegać tylko kompilujące się i działające przykłady.
17