趣味で使うために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の整理していなかった...

