DataGridのコピー機能が、日本語限定でバグってる(参)

コピー元となる範囲(行と列)を把握する必要がある。DataGridコントロールから提供されるのは、SelectedCellsというセル単位の情報なので、これを行(Item)と列の情報に変換する。後々使うこともありそうなので、クラスと拡張メソッドを実装する。
まずは、クラス。折角なので、C#6っぽく書く。

/// <summary>
/// DataGrid 選択範囲情報用クラス
/// </summary>
public class DataGridSelectedRange {

#region プロパティ

/// <summary>
/// Copy Source Item(Key:RowIndex, Value:Item)
/// </summary>
public IDictionary<int, object> SelectedItems {
get; set;
} = new Dictionary<int,object>();

/// <summary>
/// 列インデックスリスト
/// </summary>
public IList<int> ColIndexList {
get; set;
} = new List<int>();

/// <summary>
/// 範囲の列最小インデックス
/// </summary>
public int MinColIndex {
get; private set;
} = int.MaxValue;

/// <summary>
/// 範囲の列最大インデックス
/// </summary>
public int MaxColIndex {
get; private set;
} = -1;

#endregion

#region public メソッド

/// <summary>
/// 列インデックスの最大、最小を更新します。
/// </summary>
public void UpdateMinMax() {

this.MinColIndex = int.MaxValue;
this.MaxColIndex = -1;

if (this.ColIndexList == null || this.ColIndexList.Count == 0) {
return;
}

foreach (var index in this.ColIndexList) {

if (this.MinColIndex > index) {
this.MinColIndex = index;
}

if (this.MaxColIndex < index) {
this.MaxColIndex = index;
}
}
return;
}

#endregion
}

次、拡張メソッド。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Data;

//namespaceは割愛

public static class WpfHelper {

/// <summary>
/// DataGridの選択セルリストから、選択範囲情報を生成します。
/// </summary>
/// <param name="dataGrid">Target DataGrid</param>
/// <returns>選択範囲情報</returns>
public static DataGridSelectedRange GetSelectedRange(this DataGrid dataGrid) {

var selectedCells = dataGrid.SelectedCells.Where(
cellInfo => cellInfo.Column.Visibility == Visibility.Visible).ToArray();

if (selectedCells.Length == 0) {
return new DataGridSelectedRange();
}

var selectedRange = new DataGridSelectedRange();
var selectedItems = new HashSet<object>();

foreach (var cellInfo in selectedCells) {

if (!selectedItems.Contains(cellInfo.Item)) {
selectedItems.Add(cellInfo.Item);
}

if (!selectedRange.ColIndexList.Contains(cellInfo.Column.DisplayIndex)) {
selectedRange.ColIndexList.Add(cellInfo.Column.DisplayIndex);
}
}

selectedRange.UpdateMinMax();

var collectionView = CollectionViewSource.
GetDefaultView(dataGrid.ItemsSource) as ListCollectionView;

foreach (var item in selectedItems) {

var index = collectionView?.IndexOf(item) ?? dataGrid.Items.IndexOf(item);

if (!selectedRange.SelectedItems.ContainsKey(index)) {
selectedRange.SelectedItems[index] = item;
}
}

return selectedRange;
}
}
最小値、最大値を求めるメソッドはLINQにあるけど、各々メソッドで実装されているので、両方の値が欲しいときは使いにくい。両方求める拡張メソッドを作っても良いかもしれない。
続く。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m