XAMLを使わないWPF入門27「ListView + 右クリック・コンテキストメニュー表示」

コンピュータ

ListViewで右クリックするとコンテキストメニューを表示します。

ListVeiwで右クリックイベントを拾い、選択されているListViewItemを検索し、コンテキストメニュー表示の流れになります。

実行時スクリーンショット

image

右クリック→コンテキストメニュー
image

メニューアイテムをクリック
image

ファイル名:NoXAML27ListViewContextmenu.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:App.cs


using System;
using System.Windows;

namespace NoXAML27ListViewContextmenu;

public class App : Application
{
    [STAThread]
    public static void Main(string[] args)
    {
        var app = new App();
        app.Run();
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        var win = new MainWindow();
        win.Show();
    }
}

ファイル名:AssemblyInfo.cs


using System.Windows;

[assembly:ThemeInfo(
    ResourceDictionaryLocation.None,            //where theme specific resource dictionaries are located
                                                //(used if a resource is not found in the page,
                                                // or application resource dictionaries)
    ResourceDictionaryLocation.SourceAssembly   //where the generic resource dictionary is located
                                                //(used if a resource is not found in the page,
                                                // app, or any theme specific resource dictionaries)
)]

ファイル名:MainWindow.cs


using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace NoXAML27ListViewContextmenu;

public class ItemData
{
    public string Name { get; set; } = "";
}

public class MainWindow : Window
{
    private ListView _listView;

    public MainWindow()
    {
        Title = "NoXAML ListView 右クリックメニュー";
        Width = 350;
        Height = 250;

        // データ
        var items = new List<ItemData>
        {
            new ItemData { Name = "りんご" },
            new ItemData { Name = "ばなな" },
            new ItemData { Name = "みかん" },
        };

        _listView = new ListView
        {
            ItemsSource = items
        };

        var gridView = new GridView();
        _listView.View = gridView;

        // Name列のみ
        gridView.Columns.Add(new GridViewColumn
        {
            Header = "Name",
            DisplayMemberBinding = new System.Windows.Data.Binding("Name"),
            Width = 220
        });

        // マウス右クリックイベント
        _listView.PreviewMouseRightButtonDown += ListView_PreviewMouseRightButtonDown;

        this.Content = _listView;
    }

    // 右クリックでコンテキストメニュー表示
    private void ListView_PreviewMouseRightButtonDown(object? sender, MouseButtonEventArgs e)
    {
        if (e.OriginalSource is not DependencyObject dependencyObject) return;

        var item = VisualUpwardSearch<ListViewItem>(dependencyObject);
        if (item != null)
        {
            item.IsSelected = true; // 右クリックしたアイテムを選択状態にする

            // メニュー生成
            var menu = new ContextMenu();
            var menuItem1 = new MenuItem { Header = "詳細表示" };
            menuItem1.Click += (s, args) =>
            {
                var data = item.DataContext as ItemData;
                MessageBox.Show($"詳細: {data?.Name}", "詳細表示");
            };
            menu.Items.Add(menuItem1);

            // 必要なら追加のメニューもここで
            // var menuItem2 = new MenuItem { Header = "削除" };
            // menu.Items.Add(menuItem2);

            item.ContextMenu = menu;
            menu.IsOpen = true;

            e.Handled = true; // イベントバブル防止
        }
    }

    // 指定タイプの親を遡って探すヘルパー
    static T? VisualUpwardSearch<T>(DependencyObject source) where T : DependencyObject
    {
        while (source != null && !(source is T))
            source = System.Windows.Media.VisualTreeHelper.GetParent(source);
        return source as T;
    }
}

コメント