WPF にてコードでメニューを作る方法がイマイチ解らない。
というか作れたとしてどう考えてもベタ打ちな方法しかできないだろう。
ここは GtkUIManager のように XML で綺麗に作りたい。
そのための XAML じゃないか!
でもメニューとか個別パーツのみを XAML にするってできるのかな?
ということでやってみた。
いくら探しても文字列から XAML を読み込む方法が見つからない。
CLR にはデルヒャァの TStringStream みたいなのは無いの?
しかたがないので XAML ファイルを別に用意する。
<Menu xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <MenuItem Header="ファイル(_F)"> <MenuItem Header="開く(_O)" InputGestureText="Ctrl+O" Name="menu_open" /> <Separator/> <MenuItem Header="終了(_Q)" InputGestureText="Ctrl+Q" x:Name="menu_close" /> </MenuItem> </Menu>
というメニューのみの XAML を仮に作ってみた。
一番の親に CLR 名前空間定義は必須のようです。
IronPython はコンパイルしないので InitializeComponent() できない。
ので XAML 内でハンドラ指定はできないようだ、いくら試してもエラーばかり。
とりあえず上記に ui.xaml という名前を付けて。
# -*- coding: UTF-8 -*- import sys import clr clr.AddReferenceByPartialName("PresentationCore") clr.AddReferenceByPartialName("PresentationFramework") clr.AddReferenceByPartialName("WindowsBase") from System import * from System.Windows import * from System.Windows.Controls import * from System.IO import * from System.Windows.Markup import XamlReader class MoviePlayer(Window): def __init__(self): self.Title = "メニューだよ" # Menu を GtkUIManager 風に読み込む # ようにしたいけど今はこれが精一杯 i = sys.argv[0].rindex("\\") xaml_path = sys.argv[0][:i] + "\\ui.xaml" f = FileStream(xaml_path, FileMode.Open, FileAccess.Read) _menu = XamlReader.Load(f) DockPanel.SetDock(_menu, Dock.Top) _menu.Items[0].Items[0].Click += self.on_open _menu.Items[0].Items[2].Click += self.on_close # DockPanel dpanel = DockPanel() dpanel.LastChildFill = False dpanel.Children.Add(_menu) # self self.Content = dpanel self.Width = 320 self.Height = 240 def on_open(self, sender, e): MessageBox.Show("わーい") def on_close(self, sender, e): self.Close() if __name__ == "__main__": a = Application() a.Run(MoviePlayer())
何をやっているかはなんとなく解ると思う。
とりあえずパーツのみの XAML は可能だと解った。
少しだけ GtkUIManager 風に作れたが Items の順番でハンドラ指定では…
の最後みたいな処理を作るしかないかな?それはそれで難しくは無いけど。
もっと Name プロパティからスマートに指定できそうなんだけど…続くかも。