Jaký by byl kurz sázek na to, zda bude vybraná desktopová aplikace používat více než jedno okno? Mizivý… Dá se předpokládat, že hlavní průzor do duše programu doplní další okénka – dialogy, reporty, monology… Spolu s tím bude potřeba řešit, jak mezi nimi zajistit plynulou komunikaci. Podívejme se, jak na to v WPF.
Poznámka bokem: Možná vám připadá zvláštní spojení „v WPF“, i mně se zdá krátká předložka všelijaká. Vychází ovšem z toho, že mám ve zvyku číst WPF po anglicku, tedy „dabljů-pí-ef“. Zkuste si to, pak už to dává smysl ;).
Co je vlastně myšleno komunikací mezi okny? To hlavní vytvoří instanci podokna (dejme tomu jednoduchého dialogu), do kterého uživatel zadá nějaké informace (třeba jméno a příjmení nového kamaráda). Pochopitelně je žádoucí, aby se data nějakým způsobem dostala do paměťových pařátů hlavního okna, protože existence dialogu končí s jeho zavřením (není to nutné, nicméně běžné a v našem imaginárním programu jsme tak rozhodli).
WPF nabízí několik možností, jak si informace mezi okny předat.
Application.Current.MainWindow
Za prvé je každému oknu dostupná vlastnost MainWindow
, která vrací odkaz na instanci toho hlavního z nich.
Window main = Application.Current.MainWindow; // vlastnost MainWindow představuje hlavní okno Window win = Application.Current.Windows[0]; // kolekce Windows obsahuje všechna okna aplikace
Jakmile získáme odkaz na okno, znamená to, že můžeme pracovat s jeho vlastnostmi a metodami (v našem případě třeba přímo vložit novou položku do veřejné kolekce kamarádů).
main.Friends.Add(...);
Tento postup je funkční, ale ne zcela korektní. Doporučuje se raději v cílovém okně vytvořit speciální metodu a nesahat na jeho data přímo.
main.AddFriend(...);
Dialog model
Pro potřeby zmíněné aplikace je druhé okno (zadání jména a příjmení) dialogem, na což WPF samozřejmě pamatuje a umožňuje jej zobrazit metodou ShowDialog()
. V takovém případě program čeká na to, co z okna vyleze, a je připraven data zpracovat.
Jak mu tedy povíme, že informace jsou k dispozici a je třeba je přijmout? Poslouží vlastnost DialogResult, kterou oplývá každé okno a která je návratovou hodnotou metody ShowDialog()
. DialogResult je typu bool?
, což znamená, že může mít hodnotu true
, false
nebo null
.
Hodnoty false
automaticky nabyde, pokud:
- je okno zavřeno křížkem,
- je okno zavřeno příkazem Zavřít ze systémové nabídky (v levém horním rohu okna),
- je okno zavřeno klávesovou zkratkou Alt+F4.
A aby byl výčet nepravd kompletní, DialogResult je také automaticky nastaven na false
, pokud je zmáčknuto tlačítko, které má nastaveno IsCancel na true
(viz obrázek). Stiskne-li uživatel klávesu Esc, je vyvolána událost Click()
takového tlačítka, okno se uzavře a ShowDialog()
vrátí false.
Naopak hodnotu true
musíme nastavit ručně, třeba v obsluze kliknutí na potvrzovací tlačítko (viz obrázek níže). Pokud mu navíc aktivujeme vlastnost IsDefault, nebude nutné na něj ani používat myš, postačí kdekoliv stisknout klávesu Enter.
A jak hlavní okno přečte data? Jednoduše si je vytáhne z veřejných vlastností definovaných v dialogu. Kód doplněný obrázky napoví…
// Dialogové okno. public partial class winAdd : Window { public string Jmeno { get; set; } public string Prijmeni { get; set; } public winAdd() { InitializeComponent(); } private void buttOk_Click(object sender, RoutedEventArgs e) { Jmeno = txtJmeno.Text; Prijmeni = txtPrijmeni.Text; DialogResult = true; // je třeba nastavit ručně, přestože tlačítko je označeno jako IsDefault // okno se samo uzavře } }
// Hlavní okno. public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void buttPridat_Click(object sender, RoutedEventArgs e) { winAdd wAdd = new winAdd(); if (wAdd.ShowDialog() == true) { txtJmeno.Text = wAdd.Jmeno; txtPrijmeni.Text = wAdd.Prijmeni; } } }
Možností je samozřejmě více, ale tyto dvě mi stojí za zaznamenání :).
Stačilo by napsat „v prostředí WPF“ nebo „pomocí WPF“ ;)
Jinak pěkný článek. DialogResult není nic nového, ale o tom, že lze přidat k názvu proměnné ‚?‘ a vynutit tak další stav null, jsem nevěděl. Takže děkuji :)
Díky :)
Otazníkem se hodnotové datové typy označují jako nullable a je možné si dovolit stejný komfort jako u referenčních typů – uložit do nich null (což je konzistentnější řešení, než volit nějakou hodnotu, která z logiky dané aplikace nemá smysl, třeba -1).
Fajn navod, len malicka uprava treba mat property nastavene na static, inak mi to nechcelo fungovat, Dik