Budowa aplikacji w technologii.net wykład 05 Polecenia i zasoby

Podobne dokumenty
Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Instrukcja laboratoryjna cz.3

Windows Presentation Foundation

Przykładowa dostępna aplikacja w Visual Studio - krok po kroku

xmlns:prism= c. <ContentControl prism:regionmanager.regionname="mainregion" />

Politechnika Poznańska Wydział Budowy Maszyn i Zarządzania

Zdarzenia i polecenia

Programowanie obiektowe i zdarzeniowe wykład 1 Wprowadzenie do programowania zdarzeniowego

Projekt Hurtownia, realizacja rejestracji dostaw produktów

WYKONANIE APLIKACJI OKIENKOWEJ OBLICZAJĄCEJ SUMĘ DWÓCH LICZB W ŚRODOWISKU PROGRAMISTYCZNYM. NetBeans. Wykonał: Jacek Ventzke informatyka sem.

Delphi podstawy programowania. Środowisko Delphi

Projekt Hurtownia, realizacja rejestracji dostaw produktów

Informatyka II. Laboratorium Aplikacja okienkowa

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Rozdział 3. Zapisywanie stanu aplikacji w ustawieniach lokalnych

1. Wprowadzenie do WPF i XAML. Tworzenie interfejsu użytkownika.

Programownie w technologii.net wykład 6 Element Binding i Data Binding

Programowanie w Javie

Laboratorium programowania urządzeń mobilnych

Command (action, transaction, polecenie)

Utworzenie aplikacji mobilnej Po uruchomieniu Visual Studio pokazuje się ekran powitalny. Po lewej stronie odnośniki do otworzenia lub stworzenia

Lokalizacja Oprogramowania

1 LINQ. Zaawansowane programowanie internetowe Instrukcja nr 1

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Korzystanie z edytora zasad grupy do zarządzania zasadami komputera lokalnego w systemie Windows XP

Programowanie obiektowe

Laboratorium Systemów SCADA

Zaawansowane aplikacje internetowe - laboratorium

Programowanie telefonów z Windows Phone 7, cz. 4

Rys. 3. Kod elementów na stronie po dodaniu kontrolek podstawowych.

Instrukcja laboratoryjna nr.4

Dodanie nowej formy do projektu polega na:

Wykład 8: klasy cz. 4

Programowanie w technologii.net wykład 4 Aplikacja i okna

MVVM i XAML w Visual Studio 2015 / Jacek Matulewski. Gliwice, cop Spis treści

Wstęp - Prosta aplikacja internetowa w technologii Java EE 5. Programowanie komponentowe 1

Wykład 5 Okna MDI i SDI, dziedziczenie

Komputerowe systemy na rynkach finansowych. wykład 5. MQL4 - funkcje operujące na obiektach wykresu

Wybieramy File->New->Project Wybieramy aplikację MFC->MFC Application jak na rysunku poniżej:

Budowa aplikacji z graficznym interfejsem użytkownika - GUI (Graphic User Interface)

Microsoft Visual C : praktyczne przykłady / Mariusz Owczarek. Gliwice, cop Spis treści

Zaawansowane aplikacje WWW - laboratorium

Builder (budowniczy) Cel: Przykład:

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Programowanie komponentowe. Przykład 1 Bezpieczeństwo wg The Java EE 5 Tutorial Autor: Zofia Kruczkiewicz

Informatyka I. Interfejs GUI wysokiego poziomu. Biblioteka Swing. Programowanie zdarzeniowe. Politechnika Warszawska Wydział Transportu 2018

Programowanie obiektowe

MVVM Light Toolkit. Julita Borkowska

Programowanie obiektowe i zdarzeniowe

Ciekawym rozwiązaniem służącym do obsługi zdarzeń dla kilku przycisków w ramach jednej aktywności może być następujący kod:

Przychodnia 0. Stwórz projekt aplikacja konsolowa lub WPF (przemyśl wybór, bo zmiana może być czasochłonna). 1. Stwórz abstrakcyjną klasę Osoba.

Analiza i projektowanie aplikacji Java

Symfonia Mała Księgowość 2013 Specyfikacja zmian

Podstawy JavaScript ćwiczenia

Programowanie obiektowe

Zasady programowania Dokumentacja

Laboratorium 1. Wzorce oprogramowania lab1, Zofia Kruczkiewicz

PROBLEMY TECHNICZNE. Co zrobić, gdy natrafię na problemy związane z użytkowaniem programu DYSONANS

Programowanie obiektowe zastosowanie języka Java SE

Programowanie zaawansowane

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

Metody Metody, parametry, zwracanie wartości

ASP.NET MVC. Podstawy. Zaawansowane programowanie internetowe Instrukcja nr 3

Aktywności są związane z ekranem i definiują jego wygląd. Dzieje się to poprzez podpięcie do aktywności odpowiedniego widoku.

Klasy i obiekty cz II

Specyfikacja API Runtime BAS 3.0

Temat: Organizacja skoroszytów i arkuszy

Dell Display Manager podręcznik użytkownika

Laboratorium 1 - Programowanie proceduralne i obiektowe

Jak używać funkcji prostego udostępniania plików do udostępniania plików w systemie Windows XP

Ustalanie dostępu do plików - Windows XP Home/Professional

Microsoft.NET: ASP.NET MVC + Entity Framework (Code First)

dr Artur Bartoszewski dr Artur Bartoszewski - Aplikacje mobilne - Wykład

Programowanie w środowisku graficznym GUI

Klasy abstrakcyjne, interfejsy i polimorfizm

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

WPF 4.5 : księga eksperta / Adam Nathan. Gliwice, cop Spis treści

Laboratorium 7 Blog: dodawanie i edycja wpisów

using System;... using System.Threading;

Programowanie Obiektowe GUI

Leszek Stasiak Zastosowanie technologii LINQ w

Dell UltraSharp UP3017 Dell Display Manager Instrukcja użytkownika

Plan. Formularz i jego typy. Tworzenie formularza. Co to jest formularz? Typy formularzy Tworzenie prostego formularza Budowa prostego formularza

Klasy cd. Struktury Interfejsy Wyjątki

MentorGraphics ModelSim

Systemy wirtualnej rzeczywistości. Komponenty i serwisy

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Kompilacja javac prog.java powoduje wyprodukowanie kilku plików o rozszerzeniu.class, m.in. Main.class wykonanie: java Main

Program szkoleniowy. 24 h dydaktycznych (18 h zegarowych) NAZWA SZCZEGÓŁY CZAS

Współbieżność w środowisku Java

Multimedia JAVA. Historia

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Architektura interfejsu użytkownika

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

SZYBKI START. Tworzenie nowego połączenia w celu zaszyfrowania/odszyfrowania danych lub tekstu 2. Szyfrowanie/odszyfrowanie danych 4

Programowanie obiektowe

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Podstawy Programowania 2

PHP 5 język obiektowy

Transkrypt:

Budowa aplikacji w technologii.net wykład 05 Polecenia i zasoby 1/52 Commands polecenia Polecenie jest wyższym poziomem abstrakcji, niż zdarzenie reprezentuje zadanie, które chce wykonać użytkownik (np. otworzyć plik, skopiować tekst do schowka, wydrukować dokument). Zdarzenia są akcjami, które użytkownik musi podjąć, aby wykonać zadanie. W standardowym scenariuszu każde polecenie może być wydane na wiele sposobów: menu, przycisk na pasku narzędzi, skrót klawiaturowy, etc. System poleceń w WPF pozwala wydzielić abstrakcję zadań i utworzyć połączenie miedzy akcją (lub kontrolką) uruchamiającą polecenie a wykonującą je metodą. Pozwala to przenieść kod wykonujący zadania poza kod kontrolek i zdarzeń (w dobrze zaprojektowanej aplikacji logika nie powinna być umieszczona w handlerach zdarzeń, ale metodach wyższego poziomu), a jedno polecenie może być powiązane z wieloma elementami interfejsu użytkownika. Polecenie może być wyłączone, co dezaktywuje uruchamiające je kontrolki.

Rozwiązanie przy użyciu zdarzeń (handler jest tylko przekaźnikiem między interfejsem a logiką): rozwiązanie przy użyciu poleceń: (za: Pro WPF in C# 2010 Windows Presentation Foundation in.net 4, Matthew MacDonald) 2/52

3/52 Składniki modelu poleceń w WPF: Command obiekt reprezentujący polecenie/ zadanie do wykonania (nie zawiera jednak kodu je wykonującego) CommandSource kontrolka lub akcja wywołująca polecenie CommandBinding obiekt łączący polecenie z jego wykonawcą (handlerem) CommandTarget element, na którym wykonywana jest akcja np. pole tekstowe na którym wykonywane jest Copy

4/52 Interfejs ICommand public interface ICommand { void Execute(object parameter); bool CanExecute(object parameter); event EventHandler CanExecuteChanged; } Execute uruchamia polecenie (ale nie zawiera logiki zadania) CanExecute zwraca stan polecenia (czy jest włączone) CanExecuteChanged zdarzenie wywoływane, gdy stan polecenia ulega zmianie

Interfejs ICommand RoutedCommand jest jedyną klasą bezpośrednio implementującą interfejs ICommand. Daje ona wsparcie dla zdarzeń typu tunneling oraz bubbling. Dodaje nazwę oraz kolekcję akcji myszy i klawiatury wywołujących polecenie public class RoutedCommand : ICommand { public InputGestureCollection InputGestures { get; } public string Name { get; } public Type OwnerType { get; } public bool CanExecute(Object parameter, IInputElement target) { } public void Execute(Object parameter, IInputElement target) { } } Klasa RoutedUICommand dodaje własność Text, odpowiadającą za tekst wyświetlany w kontrolkach powiązanych z poleceniem. public class RoutedUICommand : RoutedCommand { public string Text { get; set; } } 5/52

6/52 Biblioteka poleceń WPF: WPF udostępnia zastaw predefiniowanych poleceń do użytku twórcy aplikacji. Są one dostępne poprzez statyczne właściwości poniższych klas: ApplicationCommands polecenia związane ze schowkiem (np. Copy, Cut, Paste), zarządzaniem dokumentami (np. New, Open, Save, SaveAs) i operacjami poziomu aplikacji (np. Properties, Help, Print, Undo, Redo) NavigationCommands polecenia używane do nawigacji w aplikacjach o interfejsie opartym na stronach (np. BrowseBack, BrowseForward, NextPage, Refresh, IncreaseZoom) EditingCommands polecenia związane z edycją dokumentów, dotyczą poruszania się po dokumencie (MoveToLineEnd, MoveLeftByWord, MoveUpByPage), wyboru zawartości (SelectToLineEnd, SelectLeftByWord) i zmian formatowania (ToggleBold, ToggleUnderline) ComponentCommands polecenia używane przez komponenty interfejsu użytkownika (np. MoveLeft, ScrollPageUp) MediaCommands polecenia związane z zarządzaniem multimediami (np. Play, Pause, NextTrack, IncreaseVolume) Część z predefiniowanych poleceń ma już zdefiniowane domyślne połączenie z akcją (popularnymi skrótami klawiaturowymi: Ctrl+O, Ctrl+S, Ctrl+Z, etc.).

7/52 Używanie poleceń: 1. Wybór polecenia jednego z gotowych lub zdefiniowanie własnej klasy polecenia

8/52 Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy polecenia mogą być wywoływane z kodu poprzez metodę Execute przeważnie jednak przypisujemy je do kontrolek implementujących interfejs ICommandSource: kontrolki dziedziczące z ButtonBase, odnośniki (Hyperlink), elementy list (ListBoxItem) i menu (MenuItem) <Button Command="ApplicationCommands.Help">Help</Button> lub: <Button Command="Help">Help</Button> można też dodać: CommandParameter dodatkowy parametr dla polecenia CommandTarget element na którym ma być wykonane polecenie

Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy polecenia mogą być wywoływane z kodu poprzez metodę Execute przeważnie jednak przypisujemy je do kontrolek implementujących interfejs ICommandSource: kontrolki dziedziczące z ButtonBase, odnośniki (Hyperlink), elementy list (ListBoxItem) i menu (MenuItem) możemy dodać wiele źródeł jednego polecenia: <DockPanel> <Menu DockPanel.Dock="Top">... <MenuItem Header="Help"> <MenuItem Command="Help"></MenuItem> </MenuItem> </Menu> <StackPanel>... </StackPanel> </DockPanel> kontrolka MenuItem wykorzystuje własność Text oraz przypisany skrót do wyświetlania informacji dla użytkownika 9/52

10/52 Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy polecenia mogą być wywoływane z kodu poprzez metodę Execute przeważnie jednak przypisujemy je do kontrolek implementujących interfejs ICommandSource przypisanie polecenia akcji myszy lub klawiatury: ApplicationCommands.Help.InputGestures.Add( new MouseGesture(MouseAction.LeftDoubleClick)); ApplicationCommands.Help.InputGestures.Add( new KeyGesture(Key.H, ModifierKeys.Control)); lub: <Window.InputBindings> <KeyBinding Command="Help" Key="H" Modifiers="Ctrl"/> <MouseBinding Command="Help" MouseAction="LeftDoubleClick"/> </Window.InputBindings>

11/52 Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy 3. Stworzenie metody wykonującej polecenie private void MyHelp(object sender, ExecutedRoutedEventArgs e) { MessageBox.Show("Udało ci się uruchomić pomoc.", "Pomoc", MessageBoxButton.OK, MessageBoxImage.Information); e.handled = true; } e.command polecenie, które wywołało tę metodę e.parameter dodatkowy parametr, który mogliśmy przekazać u źródła

12/52 Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy 3. Stworzenie metody wykonującej polecenie 4. Stworzenie powiązania (CommandBinding) łączącego polecenie z wykonawcą wiąże logikę z poleceniem bez tego polecenie jest wyłączone, a kontrolki nieaktywne 5. Dodanie stworzonego powiązania do kolekcji poleceń okna // stworzenie dowiązania CommandBinding bind = new CommandBinding(); bind.command = ApplicationCommands.Help; // przypisanie handlera do obsługi zdarzenia bind.executed += MyHelp; // rejestracja dowiązania this.commandbindings.add(bind); powiązanie można dodać do dowolnego elementu, ale zazwyczaj dodawane jest do okna najwyższego poziomu zdarzenie odpalane jest przez przypisany poleceniu element, ale dzięki bubbling dotrze do elementu zawierającego powiązanie

13/52 Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy 3. Stworzenie metody wykonującej polecenie 4. Stworzenie powiązania (CommandBinding) łączącego polecenie z wykonawcą wiąże logikę z poleceniem bez tego polecenie jest wyłączone, a kontrolki nieaktywne 5. Dodanie stworzonego powiązania do kolekcji poleceń okna this.commandbindings.add( new CommandBinding(ApplicationCommands.Help, MyHelp));

14/52 Używanie poleceń: 1. Wybór polecenia 2. Przypisanie polecenia uruchamiającej je kontrolce lub/i akcji klawiatury/ myszy 3. Stworzenie metody wykonującej polecenie 4. Stworzenie powiązania (CommandBinding) łączącego polecenie z wykonawcą wiąże logikę z poleceniem bez tego polecenie jest wyłączone, a kontrolki nieaktywne 5. Dodanie stworzonego powiązania do kolekcji poleceń okna <Window...> <Window.CommandBindings> <CommandBinding Command="Help" Executed="MyHelp" /> </Window.CommandBindings>... </Window> wiązanie wykonuje się raz, niezależnie od liczby źródeł

15/52 Wyłączanie poleceń Przydatne w przypadku poleceń, które mogą być wywoływane tylko w określonych sytuacjach Włączanie/ wyłączanie odbywa się w obsłudze zdarzenia CanExecute: CommandBinding bind = new CommandBinding();... bind.canexecute += MyHelpCanExecute;... this.commandbindings.add(bind); lub: new CommandBinding(ApplicationCommands.Help, MyHelp, MyHelpCanExecute) lub: <CommandBinding Command="Help" Executed="MyHelp" CanExecute="MyHelpCanExecute"/>

16/52 Wyłączanie poleceń Przydatne w przypadku poleceń, które mogą być wywoływane tylko w określonych sytuacjach Włączanie/ wyłączanie odbywa się w obsłudze zdarzenia CanExecute: private void MyHelpCanExecute(object sender, CanExecuteRoutedEventArgs e) { if( /*... help dostępny...*/ ) e.canexecute = true; else e.canexecute = false; } uwaga: ta metoda może uruchamiać się często gdy WPF uzna, że mogła zajść jakaś zmiana można też uruchomić ręcznie, aby wymusić odświeżenie kontrolek: CommandManager.InvalidateRequerySuggested();

17/52 Przykład użycia: <Window...> <Window.CommandBindings> <CommandBinding Command="Save" Executed="MySave" CanExecute="MySaveCanExecute" /> </Window.CommandBindings> <StackPanel> <TextBox TextChanged="MyTextChanged"></TextBox> <Button Command="Save">Save</Button> </StackPanel> </Window>

public partial class Window1 : Window { public Window1() { InitializeComponent(); IsDirty = false; } private bool IsDirty { get; set; } } private void MySave(...) { IsDirty = false; } private void MySaveCanExecute(...) { e.canexecute = IsDirty; } private void MyTextChanged(...) { IsDirty = true; } 18/52

19/52 Techniki zaawansowane definiowanie własnych poleceń public class PizzaCommands { private static RoutedUICommand piecz; static PizzaCommands() { piecz = new RoutedUICommand( "Upiecz Pizzę", "Piecz", typeof(pizzacommands)); // dobrym pomysłem jest dodanie tutaj // skrótów klawiatury: piecz.inputgestures.add(new KeyGesture(Key.P, ModifierKeys.Control)); } public static RoutedUICommand Piecz { get { return piecz; } } }

20/52 Techniki zaawansowane definiowanie własnych poleceń <Window... xmlns:app="clr-namespace:wpfapplication1"... > <Grid>... <Button Command="app:PizzaCommands.Piecz"> Upiecz Pizzę </Button>... </Grid> </Window> Przed przypisaniem polecenia kontrolce, musimy zmapować własną przestrzeń nazw do zrozumiałej przez XAMLa (WpfApplication1 to nazwa projektu, app to wybrany alias).

Techniki zaawansowane wykorzystanie własności Text własność Text zawiera opisową nazwę polecenia; niektóre kontrolki (np. MenuItem) same go wykorzystują, w wypadku Buttonów możemy zrobić to ręcznie: <Button Command="SaveAs" Content="{x:Static ApplicationCommands.SaveAs}"></Button> jednak w ten sposób uzyskamy jedynie nazwę pobraną z ToString, a nie opisowy tekst polecenia; do tego lepiej wykorzystać wiązanie (o wiązaniach więcej na kolejnym wykładzie): <Button Command="SaveAs" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"></Button> można go użyć również np. w tooltipie: <Button Command="SaveAs" ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"> <Image... /> </Button> 21/52

22/52 Techniki zaawansowane kontrolki z wbudowaną obsługą poleceń Niektóre kontrolki do wprowadzania danych mają wbudowaną obsługę poleceń (np. TextBox obsługuje polecenia Cut, Copy, Paste). Przyciski z przypisanymi poleceniami, umieszczone w toolbarze lub menu automatycznie to obsłużą, bez dowiązywania jakiejkolwiek logiki. Kontrolki same (po focusie) rozpoznają kiedy polecenie może być wywołane oraz co jest elementem docelowym. <StackPanel> <ToolBar>... <Button Command="Paste">Paste</Button> </ToolBar> <TextBox Name="txtBox"></TextBox> <WrapPanel>... <Button Command="Paste">Paste</Button> </WrapPanel> </StackPanel>

23/52 Techniki zaawansowane kontrolki z wbudowaną obsługą poleceń Niektóre kontrolki do wprowadzania danych mają wbudowaną obsługę poleceń (np. TextBox obsługuje polecenia Cut, Copy, Paste). Przyciski z przypisanymi poleceniami, umieszczone w toolbarze lub menu automatycznie to obsłużą, bez dowiązywania jakiejkolwiek logiki. Kontrolki same (po focusie) rozpoznają kiedy polecenie może być wywołane oraz co jest elementem docelowym. <StackPanel> <ToolBar>... <Button Command="Paste">Paste</Button> </ToolBar> <TextBox Name="txtBox"></TextBox> <WrapPanel>... <Button Command="Paste">Paste</Button> </WrapPanel> </StackPanel>

24/52 Techniki zaawansowane kontrolki z wbudowaną obsługą poleceń W wypadku kontrolek poza menu czy toolbarem możemy samodzielnie wskazać element docelowy polecenia: <TextBox Name="txtBox"></TextBox> <WrapPanel>... <Button Command="Paste" CommandTarget="{Binding ElementName=txtBx}"> Paste</Button> </WrapPanel> lub kazać poszukiwać go w elementach nadrzędnych (hierarchii zagnieżdżenia) <WrapPanel FocusManager.IsFocusScope="True">... <Button Command="Paste">Paste</Button> </WrapPanel>

25/52 Techniki zaawansowane kontrolki z wbudowaną obsługą poleceń W wypadku kontrolek poza menu czy toolbarem możemy samodzielnie wskazać element docelowy polecenia: <TextBox Name="txtBox"></TextBox> <WrapPanel>... <Button Command="Paste" CommandTarget="{Binding ElementName=txtBx}"> Paste</Button> </WrapPanel> lub kazać poszukiwać go w elementach nadrzędnych (hierarchii zagnieżdżenia) <WrapPanel FocusManager.IsFocusScope="True">... <Button Command="Paste">Paste</Button> </WrapPanel>

26/52 Techniki zaawansowane kontrolki z wbudowaną obsługą poleceń Gdy chcemy wyłączyć polecenie kontrolki: niekiedy mamy gotową flagę, np. TextBox pozwala na ustawienie IsUndoEnabled, aby wyłączyć Undo możemy też dodać własne wiązanie do tego polecenia, które dostarczy CanExecuted zawsze zwracające false: CommandBinding commandbinding = new CommandBinding( ApplicationCommands.Cut, null, SuppressCommand); txtbox.commandbindings.add(commandbinding); i: private void SuppressCommand(...) { e.canexecute = false; e.handled = true; }

27/52 Techniki zaawansowane kontrolki z wbudowaną obsługą poleceń Gdy chcemy wyłączyć polecenie kontrolki: niekiedy mamy gotową flagę, np. TextBox pozwala na ustawienie IsUndoEnabled, aby wyłączyć Undo możemy też dodać własne wiązanie do tego polecenia, które dostarczy CanExecuted zawsze zwracające false akcję (np. skrót klawiaturowy) uruchamiające to polecenie możemy związać poleceniem to nie jest polecenie : KeyBinding keybinding = new KeyBinding( ApplicationCommands.NotACommand, Key.C, ModifierKeys.Control); txt.inputbindings.add(keybinding);

28/52 Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) <StackPanel> <ToolBar> <Button Command="Cut">Cut</Button> <Button Command="Copy">Copy</Button> <Button Command="Paste">Paste</Button> </ToolBar> <TextBox ></TextBox> <TextBox ></TextBox> </StackPanel>

29/52 Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) Jak uzyskać ten efekt dla innych poleceń? <Window...> <Window.CommandBindings> <CommandBinding Command="Save" Executed="MySave" CanExecute="MySaveCanExecute" /> </Window.CommandBindings> <StackPanel> <ToolBar>... <Button Command="Save">Save</Button> </ToolBar> <TextBox TextChanged="MyTextChanged"></TextBox> <TextBox TextChanged="MyTextChanged"></TextBox> </StackPanel> </Window>

30/52 Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) Jak uzyskać ten efekt dla innych poleceń? <Window...> <Window.CommandBindings> <CommandBinding Command="Save" Executed="MySave" CanExecute="MySaveCanExecute" /> </Window.CommandBindings> <StackPanel> <ToolBar>... <Button Command="Save">Save</Button> </ToolBar> <TextBox TextChanged="MyTextChanged"></TextBox> <TextBox TextChanged="MyTextChanged"></TextBox> </StackPanel> </Window>

Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) Jak uzyskać ten efekt dla innych poleceń? private Dictionary<object, bool> isdirty = new...; private void MySave(...) { isdirty[e.source] = false; } private void MySaveCanExecute(...) { if (isdirty.containskey(e.source) && isdirty[e.source]) e.canexecute = true; else e.canexecute = false; } private void MyTextChanged(...) { isdirty[e.source] = true; } 31/52

32/52 Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) Jak uzyskać ten efekt dla innych poleceń? e.source zwraca element docelowy polecenia, jeżeli: kontrolka wywołująca polecenie znajduje się w toolbarze przypisaliśmy ręcznie CommandTarget nakażemy poszukiwania elementu poprzez FocusManager.IsFocusScope w przeciwnym wypadku e.source będzie kontrolką, która wywołała zdarzenie Możemy również tworzyć osobne wiązanie dla każdego pola tekstowego: <TextBox TextChanged="MyTextChanged"> <TextBox.CommandBindings> <CommandBinding Command="Save" Executed="MySave" CanExecute="MySaveCanExecute" /> </TextBox.CommandBindings> </TextBox>

33/52 Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) Jak uzyskać ten efekt dla innych poleceń? e.source zwraca element docelowy polecenia, jeżeli: kontrolka wywołująca polecenie znajduje się w toolbarze przypisaliśmy ręcznie CommandTarget nakażemy poszukiwania elementu poprzez FocusManager.IsFocusScope w przeciwnym wypadku e.source będzie kontrolką, która wywołała zdarzenie Możemy również tworzyć osobne wiązanie dla każdego pola tekstowego. Teraz sender powie nam dla którego pola została wywołana metoda: private void MySave(object sender, ExecutedRoutedEventArgs e) { string text = ((TextBox)sender).Text; MessageBox.Show("Dane do zapisania: " + text);... }

34/52 Techniki zaawansowane wykorzystanie tego samego polecenia w kilku miejscach Efekt polecenia zależy od elementu docelowego (np. gdy mamy dwa pola tekstowe w oknie, Cut, Copy, Paste działają dla jednego z nich, zależnie od focusa) Jak uzyskać ten efekt dla innych poleceń? Nieco nieeleganckie jest tworzenie wiązania osobno dla każdego pola, ale da się to rozwiązać definiując zasób: <Window.Resources> <CommandBinding x:key="binding" Command="Save" Executed="MySave" CanExecute="MySaveCanExecute"> </CommandBinding> </Window.Resources> i używając go: <TextBox.CommandBindings> <StaticResource ResourceKey="binding"></StaticResource> </TextBox.CommandBindings>

35/52 Techniki zaawansowane parametr przekazywany do Command niektóre polecenia wymagają dodatkowego parametru można odczytać go z innej kontrolki: <Button Command="NavigationCommands.Zoom" CommandParameter="{Binding ElementName=txtZoom, Path=Text}"> Zoom To Value </Button> Ograniczenia systemu poleceń: Polecenie może zmieniać automatycznie jedynie własność IsEnabled. Użyteczne mogłoby być też IsChecked, niestety, należy robić to ręcznie. Nie ma zbudowanych mechanizmów do śledzenia historii wykonywanych poleceń (do Undo/Redo).

36/52 Resources zasoby W WPF można wyróżnić dwa rodzaje zasobów: Assembly resources (binary resources) pliki z danymi (binarne), wbudowane w skompilowany podzespół aplikacji (np. obrazki) działają prawie identycznie jak assembly resources w innych aplikacjach.net, jedyną różnicą jest system adresujący, wykorzystywany przy odwoływaniu się od zasobów zasobem typu assembly w aplikacjach WPF jest np. plik BAML (skompilowany plik XAML) Object resources mogą być nimi dowolne obiekty, zdefiniowany przeważnie w XAMLu, umożliwiają przechowywanie różnego rodzaju informacji w centralnym miejscu, zapobiegając powtarzaniu kodu

37/52 Dodawanie zasobów typu assembly Należy dodać odpowiednie pliki do projektu i ustawić i właściwość Build Action na Resource (w celu lepszej organizacji, pliki mogą być grupowane w foldery).

38/52

39/52

40/52 Odwoływanie się do zasobów typu assembly Obiekt StreamResourceInfo daje dostęp m. in. do typu oraz strumienia danych zasobu: StreamResourceInfo sri = Application.GetResourceStream( new Uri("images/info.png", UriKind.Relative)); ContentType zwraca string opisujący typ danych Stream strumień (typu UnmanagedMemoryStream), z którego można odczytać bajty danych Niektóre klasy mają wbudowaną obsługę zasobów i potrafią z nimi współpracować (odnajdują je przez adres URI): <Image Source="images/info.png" /> lub: image1.source = new BitmapImage( new Uri("images/info.png", UriKind.Relative));

41/52 Odwoływanie się do zasobów typu assembly Przez adres URI w przypadku zasobów zawartych w innym podzespole (bibliotece dll, z której korzysta nasza aplikacja): img.source = new BitmapImage( new Uri("ImageLibrary;component/images/winter.jpg", UriKind.Relative)); Dodawanie zasobów z Build Action na Content (i Copy to Output Directory) Warto używać, gdy: chcemy zmieniać zasób bez ponownej kompilacji zasób jest bardzo duży plik jest opcjonalny i chcemy dostarczać aplikację również bez niego jest to plik dźwiękowy Content jest wygodniejsze, niż po prostu zwykłe dostarczenie plików z aplikacją i odczytywanie ich z dysku.

42/52 Object Resources Nowy system zasobów zintegrowany z XAML Możliwość definiowania zasobów w różnych miejscach (kontrolki, okna, cała aplikacja) Zasoby obiektowe (deklaratywne, logiczne): pozwalają na zdefiniowanie obiektu raz i używanie go w wielu miejscach kodu umożliwiają przeniesienie np. szczegółów formatujących kontrolek do centralnego miejsca, w którym mogą być w łatwy sposób zmieniane gdy pewna informacja jest oddzielona od reszty aplikacja, może być modyfikowana dynamicznie

43/52 Przykład wykorzystania Object resources definiowanie zasobu: <Window.Resources> <SolidColorBrush x:key="zielony" Color="Green" /> </Window.Resources> korzystanie z zasobu: <Button Background="{StaticResource zielony}"> Statycznie </Button> <Button Background="{DynamicResource zielony}"> Dynamicznie </Button>

44/52 Kolekcja zasobów Każdy element posiada właściwość Resources, która przechowuje kolekcję zasobów (ResourceDictionary) Kolekcja zasobów może przechowywać dowolne typy obiektów Przeważnie zasoby definiowane są na poziomie okna, gdyż wszystkie dzieci mają dostęp do zasobów ojca

45/52 Zasoby statyczne i dynamiczne Zasoby statyczne, w przeciwieństwie do dynamicznych, są pobierane raz (po deklaracji w kodzie XAML) i nie reagują na zmianę zasobu z poziomu kodu this.resources["zielony"] = new SolidColorBrush(Colors.Yellow); Zasoby dynamiczne pobierane są za każdym razem, gdy są potrzebne. Ponieważ wiąże się to z dodatkowym narzutem, z zasobów dynamicznych należy korzystać tylko wtedy, gdy: zasób zależy od ustawień systemowych (np. kolory systemowe) planujemy podmieniać obiekty dynamicznie

46/52 Zasoby statyczne i dynamiczne Dlaczego jednak to działa? SolidColorBrush brush = (SolidColorBrush)this.Resources["zielony"]; brush.color = Colors.Red; Ponieważ nie podmieniliśmy obiektu, a jedynie zmieniliśmy jego stan wewnętrzny. Zaś Brush informuje każdą używającą go kontrolkę o swojej zmianie.

47/52 Techniki zaawansowane zasoby niewspółdzielone Zazwyczaj powstaje jeden obiekt, z którego korzystają wszyscy używajacy tego zasobu. Możemy jednak udostępniać każdemu jego własny obiekt można rozważać wykorzystanie tego, jeśli każdy użytkownik chce osobno modyfikować zasób lub zasobem jest coś, czego nie możemy dzielić (np. element) są jednak lepsze sposoby by to osiągnąć. <SolidColorBrush x:key="tilebrush" x:shared="false"...> </SolidColorBrush>

48/52 Techniki zaawansowane dostęp do zasobów w kodzie W ten sposób mamy dostęp do zasobów zdefiniowanych w tej kontrolce: Button cmd = (Button)sender; Brush brush = (Brush)cmd.Resources["zielony"]; Dzięki temu nie musimy znać położenia zasobu nastąpi poszukiwanie, jak w wypadku korzystania z zasobu w XAMLu: Brush brush = (Brush)cmd.FindResource("zielony"); Jest też TryFindResource(), które w razie niepowodzenia nie rzuca wyjątku, tylko zwraca null.

49/52 Zasoby aplikacji: <Application...> <Application.Resources> <SolidColorBrush x:key="zielony" Color="Green" /> <SolidColorBrush x:key="czerwony" Color="Red" /> <SolidColorBrush x:key="niebieski" Color="Blue" /> </Application.Resources> </Application> Są dostępne w całej aplikacji są trochę jak zmienne globalne: nie należy z nimi przesadzać Jeszcze wyżej w drzewie poszukiwania znajdują się zasoby systemowe

Zasoby systemowe: Udostępniane są poprzez trzy klasy (przestrzeń nazw System.Windows): SystemColors, SystemFonts, SystemParameters label.foreground = new SolidBrush(SystemColors.WindowTextColor); lub: label.foreground = SystemColors.WindowTextBrush; lub: <Label Foreground="{x:Static SystemColors.WindowTextBrush}"> Napis </Label> lub: <Label Foreground="{DynamicResource {x:static SystemColors.WindowTextBrushKey}}"> Napis</Label> 50/52

51/52 Organizacja zasobów W celu umożliwienia współdzielenia zasobów między różnymi projektami tworzy się słowniki zasobów. Są one zapisywane w plikach XAML (dołączanych do aplikacji, z Build Action ustawionym na Page. w pliku AppBrushes.xaml: <ResourceDictionary... > <SolidColorBrush x:key="zielony" Color="Green" /> <SolidColorBrush x:key="czerwony" Color="Red" /> <SolidColorBrush x:key="niebieski" Color="Blue" /> </ResourceDictionary>

52/52 Organizacja zasobów Następnie powinny być dołączone do jakiejś kolekcji zasobów w aplikacji. <Application... > <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="AppBrushes.xaml"/> <ResourceDictionary Source="..."/> </ResourceDictionary.MergedDictionaries> <SolidColorBrush x:key="inne zasoby"... />... </ResourceDictionary> </Application.Resources> </Application>