[WPF] Rectangleにクリックイベントをつける方法

どうやるか?

Rectangleにはクリックイベントがないので、Buttonの中にRectangleを置く。
これで見かけ上はRectangleにクリックイベントがつけられる。

今回の方法は、
「ボタンを配置したいが、マウスオーバー等のイベントは不要。しかも、コードからマウスのイベントを変更するのも面倒。何よりRectangleが置きたいんだ!」 
という時くらいにしか使わなそう...

サンプル内容

Rectangle(実際にはButton)をクリックしたら、Rectangleの色情報を出力するプログラム

コード

xaml

DataContextでSampleViewModelをバインドしている。
なお、HeightやWidthなどの今回関係ない要素は省略している。

SampleView.xaml
<Grid>
  <Grid.DataContext>
     <ViewModels:SampleViewModel />
  </Grid.DataContext>
    <Button x:Name="PrintColorHexBtn" Command="{Binding PrintColorHexCommand}" CommandParameter="{Binding ElementName=PrintColorHexBtn}">
        <Button.Template>
            <ControlTemplate>
                <Rectangle Name="SampleRectangle" Fill="#ff0000"/>
            </ControlTemplate>
        </Button.Template>
  </Button>
</Grid>

DelegateCommand

DelegateCommand.cs
// 引数ありのCommandクラス
public class DelegateCommand<T> : ICommand
    {
        private readonly Action<T> _execute;
        private readonly Func<bool> _canExecute;

        public event EventHandler CanExecuteChanged;

        public DelegateCommand(Action<T> execute) : this(execute, () => true)
        {
        }

        public DelegateCommand(Action<T> execute, Func<bool> canExecute)
        {
            this._execute = execute;
            this._canExecute = canExecute;
        }

        public void Execute(object parameter)
        {
            this._execute((T)parameter);
        }

        public bool CanExecute(object parameter)
        {
            return this._canExecute();
        }
    }

ViewModel

SampleViewModel.cs
public class SampleViewModel
    {
        public SampleViewModel()
        {
            this.PrintColorHexCommand = new DelegateCommand<Button>(PrintColorHex);
        }

        public ICommand PrintColorHexCommand { get; set; }

        private void PrintColorHex(Button btn)
        {
            const string RectangleElementName = "SampleRectangle";
            // クリックされたButtonの子の中からRectangleを見つける
            Rectangle rectangle = btn.Template.FindName(RectangleElementName, btn) as Rectangle;
            Console.WriteLine(rectangle.Fill.ToString()); // -> 今回だと"#ff0000"が出力される
        }

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.