Dlaczego podejście drugie? Ponieważ już raz pisałem o generowaniu Menu, ale trochę w inny sposób i w innym środowisku. Wtedy po prostu tworzyłem obiekty Xwt.MenuItem
. Teraz zmieniłem podejście. Interfejs IMenuElement
określa minimalny wspólny interfejs obiektów menu w dowolnym frameworku jakiego będę używał. I na podstawie definicji menu złożenej z obiektów IMenuElement
będę generował odpowiednią strukturę obiektów.
WPF
Zacząłem od implementacji w WPF-ie. Wiedziałem, że praca w kodzie, bez XAMLa, może być troszkę skomplikowana, ale nie aż tak. Ilość dokumentacji jest minimalna, a wszystkie tutoriale odwołują się do XAMLa. Dopiero po jakiejś 1.5 godzinie szukania i próbowania do czegoś doszedłem.
Wygląda to tak, że MainWindow
posiada własność Content
, która domyślnie (co wynika z XAMLa) jest obiektem typu Grid
. Do niego będę chciał włożyć obiekt typu Menu
, który najpierw muszę stworzyć. Aby projekt miał przynajmniej ręce (a jak będzie miał nogi to jeszcze lepiej) zamiast generować menu w MainWindow
, postanowiłem stworzyć nową klasę MenuBuilder
, która przyjmuje IMenuProvider
w konstruktorze. IMenuProvider
dostarcza nam kolekcję obiektów IMenuElement
dla menu najwyższego poziomu.
Jak wygląda MenuItem
? Ma niezliczoną ilość własności i metod, co jest strasznie skomplikowane dla kogoś kto dopiero zabawę z WPF-em. Ale udało mi się dojść do kilku rzeczy:
Header
– nagłówek, odpowiadaIMenuElement.Label
IsCheckable
&IsChecked
– czy można zaznaczać i jeśli tak to czy jest zaznaczony, odpowiadaIMenuElement.Checked
IsEnabled
– czy da się kliknąć, odpowiadaIMenuElement.Enabled
Icon
– ikona przycisku, tylko nieliczni wybrańcy posiadającyIconAttribute
będą mieli ikonki z zestawu domyślnychItems
– dzieci obiektu, więc także elementy podmenuClick
– zdarzenie na wciśnięcie, odpowiada metodzieIMenuElement.Command(object, EventArgs)
Tag
– dowolny obiekt pozwalający na identyfikację, wykorzystuję go do przechowywania obiektuIMenuElement
, z któregoMenuItem
został wygenerowany.
Początkowo zamiast eventu Click
chciałem utworzyć obiekt typu ICommand
, co opisał Konrad Kokosa na swoim blogu (WPF oraz ICommand), ale w sumie to go nie potrzebowałem.
Więc mój MenuBuilder
buduje całe drzewo menu, oraz udostępnia je we własności RootMenu
. Teraz w MainWindow
poproszę o to menu i dodam je do kolekcji Grid
a, o którym wspomniałem wyżej.
Efekt końcowy: