2010年08月27日

MenuItemをバインド /WPF

WPF の MenuItem をバンディングで表現してみようのコーナー。ブラウザのブックマークをサンプルにしてみます。

まずはブックマークを表す VM のクラスを用意。

// Bookmark.cs
public class Bookmark { // INotifyPropertyChanged は略
    public string Title { get; set; }
    public string Url { get; set; }
    public Bookmark(string title, string url) {
        this.Title = title;
        this.Url = url;
    }
}

これを元に、メニューの XAML を記述します。

<!-- Window1.xaml -->
<Window x:Class="Sample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <DockPanel>
    <Menu DockPanel.Dock="Top">
      <MenuItem Header="ブックマーク(_B)"
         ItemsSource="{Binding}" DisplayMemberPath="Title"/>
    </Menu>
    <WebBrowser x:Name="browser"/>
  </DockPanel>
</Window>

あとは DataContext に Bookmark のコレクションを設定します。Application の Startup でやるようにしておきます。

// App.xaml.cs
private void App_Startup(object sender, StartupEventArgs e) {
    Window1 window = new Window1();
    ObservableCollection<Bookmark> bookmarks =
        new ObservableCollection<Bookmark>();
    bookmarks.Add(new Bookmark("bing", "http://www.bing.com"));
    bookmarks.Add(new Bookmark("google", "http://www.google.co.jp"));
    bookmarks.Add(new Bookmark("yahoo", "http://www.yahoo.co.jp"));
    window.DataContext = bookmarks;
    window.Show();
}

ここまでは簡単だと思います。

さて、これで取り敢えずメニューは表示されるようになりますが、当然項目をクリックしても何の反応もありません。メニュー項目をクリックしたときにその URL に移動する動作が必要です。

入力への応答の記述方法はいくつかありますが、今回は CommandBinding を使用します。

<!-- Window1.xaml -->
<!-- ブックマークのメニューの部分だけ書き換え -->
<MenuItem Header="ブックマーク(_B)"
   ItemsSource="{Binding}" DisplayMemberPath="Title">
  <MenuItem.CommandBindings>
    <CommandBinding Command="Favorites" Exected="Navigate"/>
  </MenuItem.CommandBindings>
  <MenuItem.ItemContainerStyle>
    <Style TargetType="{x:Type MenuItem}">
      <Setter Property="Command" Value="Favorites"/>
      <Setter Property="CommandParameter" Value="{Binding}"/>
    </Style>
  </MenuItem.ItemContainerStyle>
</MenuItem>

NavigationCommands.Favorites は基本ライブラリが定義している RoutedCommand であり、Routed の名前通り、コマンドが呼び出されると要素ツリー内の CommandBinding を検索してくれます。つまり、親の MenuItem の CommandBindings に Favorites を設定しておけば子 MenuItem の全ての Command を拾ってくれるって事です。ショートカットキー「Ctrl + I」が定義されているのが難点ですが、ここではおいておきます。

ItemContainerStyle は、ItemsSource を元に作られる各子 MenuItem 自体の Style です。

Favorites コマンドで実行されるメソッド(Navigate)内でどのアイテムがクリックされたか判定するために、CommandParameter を使います。子 MenuItem の DataContext は Bookmark オブジェクトになるため、この DataContext そのものである Bookmark オブジェクトがパラメータになります。

あとは CommandBinding.Executed イベントで呼び出される Navigate メソッドです。

// Window1.xaml.cs
private void Navigate(object sender, ExectedRoutedEventArgs e) {
    Bookmark bm = e.Parameter as Bookmark;
    if (bm != null) {
        this.browser.Navigate(new Uri(bm.Url));
    }
}

次のステップは CompositeCollection を使う場合 および 階層メニューを表示する場合

posted by Hongliang at 00:49| Comment(0) | TrackBack(0) | WPF | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック

ここ(hongliang.seesaa.net)で公開しているものについて、利用は自由に行って頂いて構いません。改変、再頒布もお好きになさって下さい。利用に対しこちらが何かを要求することはありません。

ただし、公開するものを使用、または参考したことによって何らかの損害等が生じた場合でも、私はいかなる責任も負いません。

あ、こんなのに使ったってコメントを頂ければ嬉しいです。

×

この広告は1年以上新しい記事の投稿がないブログに表示されております。