2011-11-09 79 views
1

Winforms'ListBox似乎有一個奇怪的行爲。當我將SelectionMode設置爲1時,我希望我可以單擊一個項目,並將其選中。這是真實的,但如果我點擊一個項目,上下拖動列表,選擇會改變。禁用列表框上的「拖動選擇」

現在,除了我需要在一些控件之間進行拖放之外,這不會太大。因此,當他們選擇一個項目並將其拖到列表中時,新選擇的項目實際上就是它註冊爲拖動的項目,並且發送了錯誤的項目。

因此,我通過保存對mousedown上的選定項目的引用來進一步對其進行綁定,但它作爲糟糕的用戶體驗捲起來。我的用戶將一個項目拖到另一個列表框中,這個列表框可以工作,但是原始列表框沒有選擇「正確」的項目,並且他們對第二個控件上實際放置哪個項目感到困惑。

那麼,有什麼方法可以改變這種行爲嗎?我想要在MouseDown中選擇一個項目,忽略MouseUp部分。簡單地使用這個事件似乎還不夠,我寧可不必重寫ListBox(我們必須爲正在創建的任何新類編寫文檔)。

回答

1

我想如果你打電話DoDragDrop這種行爲會消失。 Windows在拖放&放置模式時不會發送MouseOver消息。 propper拖&下降

例子:

private void listBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) 
    { 
     // Get the index of the item the mouse is below. 
     indexOfItemUnderMouseToDrag = listBox.IndexFromPoint(e.X, e.Y); 

     if (indexOfItemUnderMouseToDrag != ListBox.NoMatches) { 

      // Remember the point where the mouse down occurred. The DragSize indicates 
      // the size that the mouse can move before a drag event should be started.     
      Size dragSize = SystemInformation.DragSize; 

      // Create a rectangle using the DragSize, with the mouse position being 
      // at the center of the rectangle. 
      dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width /2), 
                  e.Y - (dragSize.Height /2)), dragSize); 
     } else 
      // Reset the rectangle if the mouse is not over an item in the ListBox. 
      dragBoxFromMouseDown = Rectangle.Empty; 

    } 

    private void listBox_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { 
     // Reset the drag rectangle when the mouse button is raised. 
     dragBoxFromMouseDown = Rectangle.Empty; 
    } 

    private void listBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) 
    { 
     if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { 

      // If the mouse moves outside the rectangle, start the drag. 
      if (dragBoxFromMouseDown != Rectangle.Empty && 
       !dragBoxFromMouseDown.Contains(e.X, e.Y)) 
      { 
        DragDropEffects dropEffect = listBox.DoDragDrop(listBox.Items[indexOfItemUnderMouseToDrag], DragDropEffects.All | DragDropEffects.Link); 

        // If the drag operation was a move then remove the item. 
        if (dropEffect == DragDropEffects.Move) {       
         listBox.Items.RemoveAt(indexOfItemUnderMouseToDrag); 

         // Selects the previous item in the list as long as the list has an item. 
         if (indexOfItemUnderMouseToDrag > 0) 
          listBox.SelectedIndex = indexOfItemUnderMouseToDrag -1; 

         else if (ListDragSource.Items.Count > 0) 
          // Selects the first item. 
          listBox.SelectedIndex =0; 
        } 
       } 
      } 
     } 
    } 

...和SelectedIndexChanged仍然有效!

+0

還有另外一個問題 - 我需要處理拖放操作和'SelectedIndexChanged'事件來顯示信息。所以,我使用了舊計時器技巧(在MouseDown上啓動一個計時器,在MouseUp上清除它,如果它滴答DoDragDrop())。我懷疑你是對的;如果我立即調用DoDragDrop,它將避免選擇模式。 – drharris

+0

處理拖放和「SelectedIndexChanged」不是問題。當您單擊項目時,選擇索引更改並右鍵事件被觸發。然後在'MouseMove'中檢查鼠標下降點離當前光標位置有多遠,並在適當的時候調用'DoDragDrop'。看看我的帖子上面 - 我添加了一個例子如何使拖放工作正常。 – rotman