2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【WPF】CommandParameterにListViewのSelectedItemを渡す

Last updated at Posted at 2022-12-24

初めに

WPFにてリストビューで選択した要素をCtrl+Cでクリップボードにコピーする実装にて躓いたので解決策を記録します。
Commandを使いまわしたかったのでSelectedIndexのBind以外の方法を検討しました。
結果、リストビューに名前を付けてCommandParameterの引数にElementNameで指定し、PathでSelectedItem(+プロパティ)を指定すればよかったみたいです。

コード

XAML

MainWindow.xaml
<Window x:Class="CopyByListView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CopyByListView"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListView Name="listView" 
                  HorizontalContentAlignment="Stretch"
                  ItemsSource="{Binding MyList}">
            <ListView.InputBindings>
                <KeyBinding Gesture="Ctrl+C" 
                    Command="{Binding CopyCommand}"
                    CommandParameter="{Binding ElementName=listView, Path=SelectedItem.Full}"/>
            </ListView.InputBindings>
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="上の句" DisplayMemberBinding="{Binding FirstHalf}"/>
                    <GridViewColumn Header="下の句" DisplayMemberBinding="{Binding LastHalf}"/>
                    <GridViewColumn Header="詠み人" DisplayMemberBinding="{Binding Writer}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

コードビハインド

MainWindow.xaml.cs
using System.Windows;

namespace CopyByListView;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();
    }
}

ViewModel

MainWindowViewModel.cs
using System.Collections.ObjectModel;
using System.Windows;

namespace CopyByListView;

public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        MyList = new ObservableCollection<MyListItem>
        {
            new MyListItem() { FirstHalf="秋の田の かりほの庵の 苫をあらみ", LastHalf="わが衣手は 露にぬれつつ", Writer="天智天皇"},
            new MyListItem() { FirstHalf="春すぎて 夏来にけらし 白たへの", LastHalf="ころもほすてふ あまの香具山", Writer="持統天皇"},
            new MyListItem() { FirstHalf="あしひきの 山鳥の尾の しだり尾の", LastHalf="ながながし夜を ひとりかも寝む", Writer="柿本人麻呂"},
            new MyListItem() { FirstHalf="田子の浦に うちいでて見れば 白たへの", LastHalf="富士の高嶺に 雪は降りつつ", Writer="山部赤人"},
            new MyListItem() { FirstHalf="奥山に もみぢ踏み分け 鳴く鹿の", LastHalf="声聞く時ぞ 秋は悲しき", Writer="猿丸太夫"},
            new MyListItem() { FirstHalf="かささぎの 渡せる橋に おく霜の", LastHalf="白きを見れば 夜ぞふけにける", Writer="中納言家持"},
            new MyListItem() { FirstHalf="あまの原 ふりさけ見れば かすがなる", LastHalf="三笠の山に いでし月かも", Writer="安倍仲麿"},
            new MyListItem() { FirstHalf="わが庵は 都のたつみ しかぞ住む", LastHalf="世を宇治山と 人は言ふなり", Writer="喜撰法師"},
        };
    }

    public ObservableCollection<MyListItem> MyList { get; }

    public DelegateCommand CopyCommand => new(
        (param) =>
        {
            if (param is string text)
            {
                Clipboard.SetText(text);
                MessageBox.Show($"クリップボードにコピーしました\r\n [{text}]");
                return;
            }
        });
}

リスト要素

クリップボードに転送したい文字列を返すプロパティを実装しています。

MyListItem
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace CopyByListView;

public class MyListItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    private string _firstHalf = string.Empty;
    public string FirstHalf
    {
        get => _firstHalf;
        set
        {
            _firstHalf = value;
            NotifyPropertyChanged();
        }
    }

    private string _lastHalf = string.Empty;
    public string LastHalf
    {
        get => _lastHalf;
        set
        {
            _lastHalf = value;
            NotifyPropertyChanged();
        }
    }

    private string _writer = string.Empty;
    public string Writer
    {
        get => _writer;
        set
        {
            _writer = value;
            NotifyPropertyChanged();
        }
    }

    public string Full => $"{FirstHalf} {LastHalf} {Writer}";
}

DelegeteCommand

なお、DelegeteCommandは自分で実装しました。

DelegeteCommand.cs
using System;
using System.Windows.Input;

namespace CopyByListView;

public class DelegateCommand : ICommand
{
    private Action<object?> _execute;

    public DelegateCommand(Action<object?> execute)
    {
        _execute = execute;
    }

    public bool CanExecute(object? parameter) => true;

    public void Execute(object? parameter) => _execute?.Invoke(parameter);

    public event EventHandler? CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

結果

image.png
↓ 選択してCtrl+C
image.png
OK!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?