0

約 1/2 百万レコードのバインドされた datagridview があり、任意の列で並べ替えることができます。GUI では、ユーザーは任意の数の行を選択できます (すべての行を CTRL+A で選択する場合もあります)。別のソースから、レコード ID の大きなリスト (最大 1000) を取得し、それらの ID のどれが選択した行に対応するかを調べる必要があります。私は多くのアプローチを試しましたが、どれも十分に高速ではありません。例えば:

SelectedRows の数は 20 万分の 1 のオーダーになる可能性があるため、選択された行のコレクションをループして ID リストで一致を探すことは問題外です。

また、ID のリスト (通常は 1000 のオーダー) をループしてみました。ID ごとに BindingSource.Find("Id", Value) を実行して、各 ID の行インデックスを取得し、行が選択されています。これは、グリッドが ID でソートされている場合は正常に機能しますが、そうでない場合、Find() のパフォーマンスは 1000 回呼び出すにはあまりにも貧弱です。

つまり、行オブジェクト ID を指定して、最大 1000 行の Row.Selected 状態をすばやく見つける方法が必要です。DataGridView または DataBinding がこれを処理できるはずですが、その方法は明らかではありません。前もって感謝します!

4

1 に答える 1

1

私は次のことを試みます:

  1. 可能であれば、DataGridViewのItemsSourceにObservableCollectionを使用してください。
  2. 行のSelectedプロパティのバインディングを、ObservableCollectionに含まれる基になるアイテムに追加します。
  3. CollectionViewSourceとフィルターを使用する

これは非常によく似た動作をするサンプルです(ただし、データがはるかに少ない場合は、非常にうまく機能すると思います)。

private ICollectionView _CarListView { get; set; }
private ObservableCollection<Car> _CarList;
public ObservableCollection CarList
{
    get
    {
        if (_CarList == null)
        {
            //Code to build the list

            //For the car filtering
            this._CarListView = CollectionViewSource.GetDefaultView(_CarList);
            this._CarListView.Filter = CarFilter;
        }
        return _CarList;
    }
}

private bool CarFilter(object item)
{
    Car car = item as Car;

    if(car.Name.Contains(FilterText))
    {
        return true;
    }
    else
    {
        return false;
    }
}

あなたの場合は、CarFilter(実際にはPredicate<T>)を微調整して、DataGridViewRowでSelectedプロパティにバインドしたプロパティを検索できるようにします。たとえば、ObservableCollectionに含まれるオブジェクトタイプにIsSelectedブール値を作成し、その項目がtrueである場所を返すことができます。フィルタリングされたリストの結果が得られたら、言及したIDの小さいリスト(約1000要素)を調べて、IDが一致する場所を確認します。2つのコレクションに対してLINQクエリを使用して、可能な限り高速な操作を実行してみます。

他のすべてが失敗した場合は、元のループ手法に戻り、並列ライブラリを試してParallel.ForEachを実行します。これにより、マルチコアCPUを活用して操作を高速化できます。ただし、ブルートフォースはしません。大きなセットから選択したアイテムを蓄積するために1つのパスを作成してから、小さなセットで選択した各アイテムを検索する必要があるようです。

于 2012-06-27T01:54:21.263 に答える