【WPF】右クリックメニューでデータグリッドの内容をコピーする

2017年11月24日C#,開発

おはようございます。

データグリッドで、
編集まではさせないけど内容のコピーが出来ると便利なシーンってありますよね。

そんな時は、右クリックでコンテキストメニューを表示して操作させるのがいいかもしれません。
ということでやってみました。

ついでに、クリップボードの内容を貼り付ける操作と、行のコピーも実装してみます。

プログラムは下記の記事のものを流用します。

スポンサーリンク

画面の修正

まずは、データグリッドにコンテキストメニューを追加します。

MainWindow.xaml

            <DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,31,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >
                <DataGrid.ContextMenu>
                    <ContextMenu>
                        <MenuItem x:Name="ctm_namecopy" Header="名前をコピー(_C)" Click="ctm_namecopy_Click"/>
                        <MenuItem x:Name="ctm_namepaste" Header="名前を貼り付け(_V)" Click="ctm_namepaste_Click"/>
                        <MenuItem x:Name="ctm_rowcopy" Header="行をCSVとしてコピー(_R)" Click="ctm_rowcopy_Click"/>
                    </ContextMenu>
                </DataGrid.ContextMenu>
                <DataGrid.Columns>
                    <DataGridTemplateColumn IsReadOnly="True" Header="選択" Width="50">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="40" />
                    <DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="False" Width="80"/>
                    <DataGridTemplateColumn IsReadOnly="True" Header="性別"  CellStyle="{StaticResource dgc-combo}" Width="50">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox Name="cmbGender" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.GenderList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                          DisplayMemberPath="Name" SelectedValuePath="Cd" SelectedValue="{Binding Sex}" Width="50" Background="Transparent"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="False" Width="40"/>
                    <DataGridTemplateColumn IsReadOnly="True" Header="種別"  CellStyle="{StaticResource dgc-combo}" Width="110">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox Name="cmbKind" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.KindList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                          DisplayMemberPath="KindName" SelectedValuePath="KindCd" SelectedValue="{Binding Kind}" Width="110" Background="Transparent"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="False" Width="*"/>
                </DataGrid.Columns>
            </DataGrid>

プログラムの修正

コピーメソッドの追加

次のようにメソッドを実装します。
MainWindow.xaml.cs

        /// <summary>
        /// 名前をクリップボードにコピーします.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ctm_namecopy_Click(object sender, RoutedEventArgs e)
        {
            // 選択中のデータを取得
            CatModel cat = this.dataGrid.SelectedItem as CatModel;
            if (cat != null)
            {
                try
                {
                    // クリップボードにコピー
                    Clipboard.SetText(cat.Name);
                }
                catch (Exception ex)
                {
                }
            }
        }

 

データベース上で選択された行の、名前列をクリップボードにコピーします。
簡単なものですね。

貼り付けメソッドの追加

次のようにメソッドを実装します。
MainWindow.xaml.cs

        /// <summary>
        /// クリップボードの名前を貼り付け
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ctm_namepaste_Click(object sender, RoutedEventArgs e)
        {
            // 選択中のデータを取得
            CatModel cat = this.dataGrid.SelectedItem as CatModel;
            if (cat != null)
            {
                String name = Clipboard.GetText();
                cat.Name = name;
                this.dataGrid.Items.Refresh();
            }
        }

 

選択された行の名前列の内容をクリップボードの内容で上書きします。
リフレッシュメソッドを呼び出すことで内容が即座に反映されます。

行コピーメソッドの追加

次のようにメソッドを実装します。
MainWindow.xaml.cs

        /// <summary>
        /// 行をカンマ区切り文字列にしてクリップボードにコピーします.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ctm_rowcopy_Click(object sender, RoutedEventArgs e)
        {
            // 選択中のデータを取得
            CatModel cat = this.dataGrid.SelectedItem as CatModel;
            if (cat != null)
            {
                // データをCSV形式に変換
                String delmiter = ",";
                StringBuilder sb = new StringBuilder();
                sb.Append(cat.No).Append(delmiter);
                sb.Append(cat.Name).Append(delmiter);
                sb.Append(cat.Sex).Append(delmiter);
                sb.Append(cat.Age).Append(delmiter);

                KindConverter kindConverter = new KindConverter();
                sb.Append(kindConverter.Convert(cat.Kind, null,null,null)).Append(delmiter);

                sb.Append(cat.Favorite);
                try
                {
                    // クリップボードにコピー
                    Clipboard.SetText(sb.ToString());
                }
                catch (Exception ex)
                {
                }
            }
        }

 

こちらはコピーの応用で、選択された行の内容をカンマ区切りに編集し
クリップボードにコピーします。

まとめ

思っていたより簡単に実装できました。
クライアントソフトならではの手軽さですかね。
(WEBはセキュリティとかの問題でコピーとかが意外に面倒)

コンテキストメニュー自体は階層も持たすことができますし、
色々なことに利用できそうですね。
何か思いついたらやってみようと思います。

ではでは。

スポンサーリンク


関連するコンテンツ

2017年11月24日C#,開発C#,WPF,プログラミング

Posted by doradora