2008-09-17 36 views
5

リストビューコントロールですべてのクリックをControlキーで処理したように扱う方法はありますか?リストビュー複数の選択

ユーザーが複数の項目を同時に簡単に選択できるように、コントロールキーを使用する機能(項目を選択して選択状態を解除する機能)を再現する必要があります。

ありがとうございます。

答えて

4

MultiSelectがtrueに設定されていても、ListViewコントロールの標準的な動作ではありません。

独自のカスタムコントロールを作成したい場合は、次の操作を実行する必要があります:

  1. は、リストビュー
  2. からの制御は、「選択」イベントにハンドラを追加派生。
  3. "OnSelected"では、選択したアイテムの独自のリストを維持します。
  4. 新しく選択したアイテムがリストにない場合は、追加します。そうであれば、取り外します。
  5. コードでは、リスト内のすべての項目を選択します。

コントロールキーを使用せずにマルチ選択のように実装して感じるだけのシンプルさが必要です。

+0

私はこれらの行に自分自身で取り組んできましたが、修正を先に進める前に、何かが簡単かどうかを確認して確認したかったのです。 あなたの答えをありがとう。 – Evan

+0

選択したアイテムのリストに、インデックスではなく「コンテンツ」が格納されていることを確認します。インデックスを使用する方が簡単ですが、ListBox.ItemsCollectionとリストを同期させておく必要があることを意味します。うまくいけばあなたのオブジェクトや文字列は、この関係を維持するのに十分なユニークです! –

-2

Ctrl +クリックの動作はブラウザによって実装されているように、実際の.NETコントロールとはほとんど関係がありません。あなたが達成しようとしている結果は、多くのJavaScriptを追加して取得することができます。最も簡単な方法は、リストビューをハックするのではなく、この方法で動作するJavaScriptコントロールをデフォルトから構築することでしょう。これが望ましいでしょうか?その場合、私はそれを調べて、解決策を得てあなたに戻ってきます。

+0

ブラウザとは関係がありません。彼はC#とWinFormsを使用しています。 –

+0

とにかく、Javascriptはwinforms環境では使用できません。 – Evan

0

ListviewItemCollectionをドリルダウンして、個々のアイテムのSelectedプロパティをtrueに設定できます。これは、あなたが再現しようとしている "マルチセレクト"機能をエミュレートすると私は信じています。 (上記のコメント欄で述べたように、lisetviewのMultiSelectプロパティをtrueに設定してください)

2

リストビューでCheckboxesを使用することをお勧めします。これは、Ctrl + Clickについて知らない普通のユーザーにマルチセレクトコンセプトを伝える明確な方法です。

MSDNのページから:

チェックボックスプロパティは、CTRLキーを使用せずに、ListViewコントロールで複数の項目を選択するための方法を提供しています。アプリケーションによっては、標準の複数選択方法ではなく項目を選択するためにチェックボックスを使用する方が、ユーザーにとってより簡単になる場合があります。 ListViewコントロールのMultiSelectプロパティがfalseに設定されていても、チェックボックスを表示して複数の選択機能をユーザーに提供できます。この機能は、複数の項目を選択する必要がなく、ユーザーがアプリケーション内で操作を実行するためにリストから複数の項目を選択できるようにしたい場合に役立ちます。

2

ここでは、WndProcを使用してこの問題を解決するために使用した完全なソリューションを紹介します。基本的に、マウスをクリックするとヒットテストが行​​われます。MutliSelectがオンの場合、アイテムは自動的にオン/オフ[.Selected]に切り替えられ、他のリストの維持やListView機能の混乱は心配しません。

私はこれをすべてのシナリオでテストしていませんが、それは私のために働いています。 YMMV。

public class MultiSelectNoCTRLKeyListView : ListView { 
    public MultiSelectNoCTRLKeyListView() { 

    } 

    public const int WM_LBUTTONDOWN = 0x0201; 
    protected override void WndProc(ref Message m) { 
    switch (m.Msg) { 
     case WM_LBUTTONDOWN: 
     if (!this.MultiSelect) 
      break; 

     int x = (m.LParam.ToInt32() & 0xffff); 
     int y = (m.LParam.ToInt32() >> 16) & 0xffff; 

     var hitTest = this.HitTest(x, y); 
     if (hitTest != null && hitTest.Item != null) 
      hitTest.Item.Selected = !hitTest.Item.Selected; 

     return; 
    } 

    base.WndProc(ref m); 
    } 
} 
2

ここでは上記のMatthew M.が提供するソリューションの修正版です。

これは改善点と追加機能を提供します。

改善: - コントロールを左クリックするとコントロールにフォーカスが移ります。 - コントロールはあなたが一度に選択することができますどのように多くのアイテムに制限を置くことを可能にするプロパティ(MultiSelectionLimit)が : - マウスの右クリックの動作が一致している(単一選択)

は、機能を追加しました。

私の最初の投稿後、私はコードに軽微な問題を認識しました。複数の選択をクリアすると、ItemSelectionChangedイベントが複数回呼び出されます。現在の継承でこれを回避する方法が見つからない可能性があるので、選択したすべての項目が選択解除されるまでboolプロパティSelectionsBeingClearedが真となるソリューションを採用しました。このようにすると、そのプロパティへの簡単な呼び出しによって、複数の選択肢のすべてがクリアされるまでエフェクトの更新を避けることができます。

public class ListViewMultiSelect : ListView 
{ 
    public const int WM_LBUTTONDOWN = 0x0201; 
    public const int WM_RBUTTONDOWN = 0x0204; 

    private bool _selectionsBeingCleared; 
    /// <summary> 
    /// Returns a boolean indicating if multiple items are being deselected. 
    /// </summary> 
    /// <remarks> This value can be used to avoid updating through events before all deselections have been carried out.</remarks> 
    public bool SelectionsBeingCleared 
    { 
     get 
     { 
      return this._selectionsBeingCleared; 
     } 
     private set 
     { 
      this._selectionsBeingCleared = value; 
     } 
    } 
    private int _multiSelectionLimit; 
    /// <summary> 
    /// The limit to how many items that can be selected simultaneously. Set value to zero for unlimited selections. 
    /// </summary> 
    public int MultiSelectionLimit 
    { 
     get 
     { 
      return this._multiSelectionLimit; 
     } 
     set 
     { 
      this._multiSelectionLimit = Math.Max(value, 0); 
     } 
    } 

    public ListViewMultiSelect() 
    { 
     this.ItemSelectionChanged += this.multiSelectionListView_ItemSelectionChanged; 
    } 

    public ListViewMultiSelect(int selectionsLimit) 
     : this() 
    { 
     this.MultiSelectionLimit = selectionsLimit; 
    } 

    private void multiSelectionListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) 
    { 
     if (e.IsSelected) 
     { 
      if (this.MultiSelectionLimit > 0 && this.SelectedItems.Count > this.MultiSelectionLimit) 
      { 
       this._selectionsBeingCleared = true; 

       List<ListViewItem> itemsToDeselect = this.SelectedItems.Cast<ListViewItem>().Except(new ListViewItem[] { e.Item }).ToList(); 

       foreach (ListViewItem item in itemsToDeselect.Skip(1)) { item.Selected = false; } 

       this._selectionsBeingCleared = false; 

       itemsToDeselect[0].Selected = false; 
      } 

     } 

    } 

    protected override void WndProc(ref Message m) 
    { 
     switch (m.Msg) 
     { 
      case WM_LBUTTONDOWN: 
       if (this.SelectedItems.Count == 0 || !this.MultiSelect) { break; } 

       if (this.MultiSelectionLimit > 0 && this.SelectedItems.Count > this.MultiSelectionLimit) { this.ClearSelections(); } 

       int x = (m.LParam.ToInt32() & 0xffff); 
       int y = (m.LParam.ToInt32() >> 16) & 0xffff; 

       ListViewHitTestInfo hitTest = this.HitTest(x, y); 

       if (hitTest != null && hitTest.Item != null) { hitTest.Item.Selected = !hitTest.Item.Selected; } 

       this.Focus(); 

       return; 
      case WM_RBUTTONDOWN: 
       if (this.SelectedItems.Count > 0) { this.ClearSelections(); } 
       break; 
     } 

     base.WndProc(ref m); 
    } 

    private void ClearSelections() 
    { 
     this._selectionsBeingCleared = true; 

     SelectedListViewItemCollection itemsToDeselect = this.SelectedItems; 

     foreach (ListViewItem item in itemsToDeselect.Cast<ListViewItem>().Skip(1)) { item.Selected = false; } 

     this._selectionsBeingCleared = false; 

     this.SelectedItems.Clear(); 
    } 
} 
0

誰かがこの記事を検索して見つけた場合、受け入れられた解決策はもはや有効ではありません。 (実際私はそれが今までにあったかどうかはわかりません)。あなたが望む(修飾キーなしで複数を選択する)ためには、単純にリストビューの選択タイプを拡張するのではなく複数にするだけです。複数のアイテムがクリックされたときに1つのアイテムを順番に選択し、拡張するには修飾キーを最初に押す必要があります。

+0

これは質問に対する答えを提供しません。十分な[評判](http://stackoverflow.com/help/whats-reputation)があれば、[任意の投稿にコメントする]ことができます(http://stackoverflow.com/help/privileges/comment)。代わりに、[質問者からの説明を必要としない回答を提供する](http://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-c​​an- i-do-代わりに)。 - [レビューの投稿](レビュー/低品質の投稿/ 13911675) –

+0

どのように質問に答えられないのか分かりません。質問は、「リストビューコントロールですべてのクリックをControlキーで処理したように扱う方法はありますか?」私が与えた答えは、「複数選択属性を複数に拡張しないように設定する」ことでした。それは、創造的な質問に対する有効で、正しい、そしてテストされた答えです。 まあ、それは私が試してみて、古い解決法を使って古い質問に出てくる他の人を助ける最後の時です。 – kamikazi