2011-04-14 90 views
2

如果在按住鼠標按鈕的同時WPF列表框獲取MouseMove事件,它將更改列表框的選擇。也就是說,如果您在項目#1上單擊鼠標,然後拖到項目#2上,它將取消選擇項目#1並選擇項目#2。 我該如何預防?防止WPF列表框在佈局更改時在鼠標下選擇項目

這是簡短的版本。稍微長一點的版本是這樣的:當用戶雙擊我的ListBox中的一個項目時,我對我的佈局做了其他更改,其中包括在ListBox上方顯示其他控件。這將ListBox向下移動,這意味着鼠標現在位於與用戶雙擊時不同的ListBoxItem上。

由於我在響應DoubleClick事件(這是一個鼠標按下事件)時進行了這些佈局更改,所以當此佈局更改完成時,很可能仍會按下鼠標按鈕,這意味着WPF將發送ListBox一個MouseMove事件(因爲鼠標的位置相對於ListBox已經改變)。 ListBox將其視爲拖動,並選擇鼠標下面的事件。

我不希望選擇在我得到雙擊事件和用戶釋放鼠標的時間(在佈局更改後可能會很好)之間進行更改。我懷疑最簡單的方法是禁用「更改拖放選擇」行爲,但我願意接受其他建議。

我怎樣才能「鎖定」雙擊選擇,並防止它改變,直到mouseup?

回答

13

經過在ILSpy的一些挖掘,我發現沒有屬性會禁用「拖動選擇」行爲,也沒有可標記爲「處理」的事件來阻止它。

但是,有一個很好的轉折點來改變這種行爲:ListBoxItem.OnMouseEnter是虛擬的,它回調到列表框中來改變選擇。它似乎沒有做任何其他實質性的事情,所以我需要做的就是重寫它,什麼都不做。

編輯:事實證明,上述內容只是在列表框中移動鼠標時,保持選擇不變。如果將鼠標移動到列表框的上方或下方,則不起作用 - 然後自動滾動將啓動並移動選擇。大多數自動滾動代碼再次處於非虛擬方法中;它看起來像防止自動滾動的最佳方法可能是禁用鼠標捕獲。 ListBoxItem上的另一個重寫可以解決這個問題。

它看起來像使用我自己的ListBoxItem後裔的最佳方式是從ListBox下降。最終代碼如下所示:

public class ListBoxEx : ListBox 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ListBoxExItem(); 
    } 
    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return item is ListBoxExItem; 
    } 
} 
public class ListBoxExItem : ListBoxItem 
{ 
    private Selector ParentSelector 
    { 
     get { return ItemsControl.ItemsControlFromItemContainer(this) as Selector; } 
    } 

    protected override void OnMouseEnter(MouseEventArgs e) 
    { 
    } 
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) 
    { 
     base.OnMouseLeftButtonDown(e); 
     ParentSelector?.ReleaseMouseCapture(); 
    } 
} 
+0

幫助解決列表項拖放操作期間的選擇更改。謝謝。 – 2012-08-23 22:37:40

+0

如果我們移除鼠標向下事件中的選定項目,'ParentSelector'將爲'null'。我們可以使用null檢查'ParentSelector?.ReleaseMouseCapture()'來解決這個問題。 – J3soon 2017-05-19 13:58:48

+0

@ J3soon很好的建議。更新。 – 2017-05-21 19:11:50

相關問題