2008-09-17 100 views
5

有什麼辦法強制listview控件將所有的點擊視爲通過Control鍵完成嗎?Listview Multiple Selection

我需要複製使用控制鍵(選擇項目設置和取消其選擇狀態)的功能,以便用戶可以輕鬆地同時選擇多個項目。

預先感謝您。

回答

4

即使將MultiSelect設置爲true,它也不是ListView控件的標準行爲。

如果你想創建自己的自定義控制,你需要做到以下幾點:

  1. 從ListView控件
  2. 派生一個控件添加一個處理程序「選定」事件。
  3. 在「OnSelected」中,維護您自己的選定項目列表。
  4. 如果新選擇的項目不在您的列表中,請添加它。如果是,請將其刪除。
  5. 在代碼中,選擇列表中的所有項目。

應該是很簡單的實現,感覺像多選不使用控制鍵!

+0

我自己一直在沿着這些方向努力,但我想在檢查修復之前檢查並確定是否有更簡單的方法。 儘管感謝您的回答。 – Evan 2008-09-17 15:01:23

-2

Ctrl + Click行爲與瀏覽器一樣,並且與實際的.NET控件無關。您試圖實現的結果可以通過很多額外的JavaScript來獲得 - 最簡單的方法可能是從默認情況下構建一個JavaScript控件,而不是試圖破解列表視圖。這會是可取的嗎?在這種情況下,我可以研究它並通過解決方案回覆給您。

+0

與瀏覽器無關,他使用C#和WinForms! – 2008-09-17 14:57:32

+0

無論如何,Javascript不能用於winforms環境。 – Evan 2008-09-17 14:58:42

0

向下鑽取ListviewItemCollection,您可以將單個項目的Selected屬性設置爲true。我相信,這將模擬您嘗試複製的「多選」功能。 (另外,正如上面提到的評論者一樣,一定要將lisetview的MultiSelect屬性設置爲true。)

2

您可能還想在列表視圖上使用Checkboxes。這是將多選概念傳達給不瞭解Ctrl + Click的普通用戶的一種顯而易見的方式。

從MSDN頁:

複選框屬性提供了一種方法來選擇ListView控件的多個項目,而無需使用CTRL鍵。根據您的應用程序,使用複選框選擇項目而不是標準多選方法可能會更容易爲用戶。即使ListView控件的MultiSelect屬性設置爲false,仍然可以顯示覆選框並向用戶提供多種選擇功能。如果您不想要選擇多個項目,但仍希望允許用戶從列表中選擇多個項目以在應用程序中執行操作,則此功能可能很有用。

2

這裏是我用WndProc解決這個問題的完整解決方案。基本上,當點擊鼠標時它會進行點擊測試..然後如果打開MutliSelect,它會自動切換項目開/關[.Selected],而不用擔心維護任何其他列表或混淆ListView功能。

我還沒有在所有場景中測試過這個...它對我有用。因人而異。

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將爲true,直到取消選擇所有選定的項目。通過這種方式,對該屬性的簡單調用將可以避免更新效果,直到所有多個選擇都被清除。

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

爲防萬一其他人搜索並找到本文,接受的解決方案不再有效。 (實際上我不確定它曾經是)。爲了做你想做的事(選擇不帶修飾鍵的倍數)只需將列表視圖選擇類型設置爲多個,而不是擴展。點擊時,多個選擇一個接一個項目,並且擴展需要首先按下修飾鍵。