趣味で使うためにVisual C# 2010 Expressをインストールしました。 ちょっとwpfを触ってみる予定です。 手始めに、このサイトを参考に簡単な画像表示ソフトを作りました。
コードはこんな感じです。
// AppCommands.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Input; using System.Windows; namespace LeisurelyImageViewer { class AppCommands { public readonly static RoutedUICommand CommandOpen= new RoutedUICommand( "開く", "CommandOpen", typeof(AppCommands), new InputGestureCollection { new KeyGesture(Key.O, ModifierKeys.Control) } ); } }
<!-- MainWindow.xaml --> <Window x:Class="LeisurelyImageViewer.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:app="clr-namespace:LeisurelyImageViewer" Title="MainWindow" Height="350" Width="525"> <Window.CommandBindings> <CommandBinding Command="{x:Static app:AppCommands.CommandOpen}" Executed="OpenFile"/> </Window.CommandBindings> <DockPanel Name="mainDockPanel"> <ScrollViewer Name="mainScrollViewer" VerticalScrollBarVisibility="Disabled" Background="Black"> <ScrollViewer.ContextMenu> <ContextMenu> <MenuItem Header="開く" Command="{x:Static app:AppCommands.CommandOpen}"/> </ContextMenu> </ScrollViewer.ContextMenu> <Image Name="mainImage" Stretch="Uniform"/> </ScrollViewer> </DockPanel> </Window>
// MainWindow.xaml.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace LeisurelyImageViewer { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void OpenFile(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); dlg.CheckFileExists = true; dlg.Filter = "Image Files(*.PNG;*.BMP;*.JPG;*.GIF)|*.PNG;*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"; if (dlg.ShowDialog() == true) { BitmapImage newImg = new BitmapImage(); newImg.BeginInit(); newImg.UriSource = new Uri(dlg.FileName); newImg.EndInit(); mainImage.Source = newImg; } } } }
単純に、ファイル選択ダイアログで選んだファイルを表示するだけです。 こんな小さなプログラムなのに問題がありました。 コンテキストメニューの「開く」がなぜかすぐにアクティブにならなかったのです。 最初に右クリックでメニューを出したときはグレー表示で、2度目か、場合によってはそれ以降メニューを出したときやっとアクティブになってました。
他の開発環境ならあっという間に検索できそうなネタですが、wpfは日本であまり普及していないらしく、解決法を探すのに少しだけ手間取りました。 英語の掲示板を機械翻訳したサイトにありました。
英語の文章はほとんど読んでません。 とりあえず対処法だけ拾いました。 すぐアクティブにするにはMenuItemにCommandTargetの設定をしなければならないようです。 意味は分からないけど、
CommandTarget="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}
とするらしい。 上のコードのContextMenuのところはこうなります。
<ContextMenu>
<MenuItem Header="開く" Command="{x:Static app:AppCommands.CommandOpen}" CommandTarget="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
後で気が向いたら意味とか仕組みとかを調べておかなくては。
メニューの項目がたった1つしかないっていうアプリケーションはあまりありません。 当然メニューの項目は2つ以上あるのが普通です。 今のところ、毎回「CommandTarget=...」と書くしかないのかなぁ? 意味とか仕組みとかがわかったら共通の設定を1箇所で済ませるような方法も分かるかもしれませんね?
あ~。 上のコード、usingの整理していなかった...