i++

プログラム系のメモ書きなど

WPF/XAML : DataGrid の行にコンテクストメニューを設定する

方針・ポイント

  • EventSetter を使って DataGridRow に右マウスボタンイベント(MouseRightButtonUp)を設定する
  • ContextMenu を DataGrid.Resources 内で作る
  • そのイベント内で、Resources の ContextMenu を取得、設定する

ContextMenu の方もコード上で作る、右クリック時ではなく行を追加した時に ContextMenu を設定するなど、他にも様々な方法で同じことが実現できると思いますが、今回は上記の方法で行います。

右マウスボタンのイベントの方が、右クリックによるコンテクストメニューの表示よりも先に行われるようなので、最初の右クリックでメニューは表示されます。

f:id:tkyjhr:20160127145816p:plain

サンプルコード

XAML
<DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False">
    <DataGrid.Resources>
        <!-- ContextMenu の作成 -->
        <ContextMenu x:Key="DataGridContextMenu">
            <MenuItem Header="Menu 1" Click="MyDataGrid_ContextMenu1_Click"/>
            <MenuItem Header="Menu 2" Click="MyDataGrid_ContextMenu2_Click"/>
        </ContextMenu>
        <!-- DataGridRow に右マウスボタンイベントの設定 -->
        <Style TargetType="{x:Type DataGridRow}">
            <EventSetter Event="MouseRightButtonUp" Handler="MyDataGrid_Row_MouseRightButtonUp"/>
        </Style>
    </DataGrid.Resources>
    <!-- 適当なサンプルデータ表示用の列 -->
    <DataGrid.Columns>
        <DataGridTextColumn Header="苗字" Binding="{Binding FamilyName}" Width="80"/>
        <DataGridTextColumn Header="名前" Binding="{Binding FirstName}" Width="80" />
    </DataGrid.Columns>
</DataGrid>
C#
public partial class MainWindow : Window
{
    // 適当なサンプルデータ用のクラス
    public class Person
    {
        public string FirstName { get; set; }
        public string FamilyName { get; set; }

        public Person(string firstName, string familyName)
        {
            FirstName = firstName;
            FamilyName = familyName;
        }
    }

    private ObservableCollection<Person> MyDataGrid_SourceCollection;

    public MainWindow()
    {
        InitializeComponent();

        // 適当サンプルデータを追加
        MyDataGrid_SourceCollection = new ObservableCollection<Person>();
        MyDataGrid_SourceCollection.Add(new Person("太郎", "山田"));
        MyDataGrid_SourceCollection.Add(new Person("花子", "佐藤"));
        MyDataGrid.ItemsSource = MyDataGrid_SourceCollection;
    }

    // DataGridRow に対する右マウスボタンイベント
    private void MyDataGrid_Row_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
    {
        // Resources から ContextMenu を取得して設定
        (sender as DataGridRow).ContextMenu = MyDataGrid.Resources["DataGridContextMenu"] as ContextMenu;
    }

    // ContextMenu の MenuItem のイベントその1
    private void MyDataGrid_ContextMenu1_Click(object sender, EventArgs e)
    {
        if (MyDataGrid.SelectedItem != null)
        {
            MessageBox.Show("Menu 1 : FirstName = " +(MyDataGrid.SelectedItem as Person).FirstName);
        }
    }

    // ContextMenu の MenuItem のイベントその2
    private void MyDataGrid_ContextMenu2_Click(object sender, EventArgs e)
    {
        if (MyDataGrid.SelectedItem != null)
        {
            MessageBox.Show("Menu 2 : FamilyName = " + (MyDataGrid.SelectedItem as Person).FamilyName);
        }
    }
}