2009-08-13 43 views
28

我想在ListBox中的某個項目被鼠標點擊時收到通知,無論它是否已被選中。如何在WPF的ListBox中的某個項目上捕獲鼠標單擊?

我搜索,發現這個:(http://kevin-berridge.blogspot.com/2008/06/wpf-listboxitem-double-click.html見註釋)

private void AddDoubleClickEventStyle(ListBox listBox, MouseButtonEventHandler mouseButtonEventHandler) 
{ 
    if (listBox.ItemContainerStyle == null) 
     listBox.ItemContainerStyle = new Style(typeof(ListBoxItem)); 
    listBox.ItemContainerStyle.Setters.Add(new EventSetter() 
    { 
     Event = MouseDoubleClickEvent, 
     Handler = mouseButtonEventHandler 
    }); 
} 

//Usage: 
AddDoubleClickEventStyle(listView1, new MouseButtonEventHandler(listView1_MouseDoubleClick)); 

這工作,但它確實是一個DoubleClick。儘管如此,我無法讓它工作。我試過MouseLeftButtonDownEvent - 因爲似乎沒有MouseClick事件,但它沒有被調用。

一個更普遍的側面問題:我如何看到存在哪些事件以及哪些處理程序與它們相對應,以及它們何時實際執行某些操作?例如,什麼告訴我,對於MouseDoubleClickEvent我需要MouseButtonEventHandler?也許對於MouseLeftButtonDownEvent我需要一些其他處理程序,這就是爲什麼它不起作用?

我也嘗試了繼承ListBoxItem並覆蓋OnMouseLeftButtonDown - 但它也不會被調用。

馬克

+0

我已經選擇用按鈕包裝每個listboxitem,而不是使用按鈕事件。 https://stackoverflow.com/questions/17057022/getting-listbox-item-index-from-button-click – Dummy 2017-06-01 04:45:54

回答

43

我相信你的MouseLeftButtonDown處理程序不被調用,因爲ListBox使用此事件在內部解僱其SelectionChanged事件(用這種思想是,在絕大多數情況下,SelectionChanged是你所需要的)。這就是說,你有幾個選擇。您可以訂閱PreviewLeftButtonDown事件。大多數路由事件都具有Bubbling的路由策略,這意味着生成該事件的控件首先獲取它,並且它不處理該事件在視覺樹上向上工作,使每個控件都有機會處理該事件。另一方面,預覽事件是隧道。這意味着它們從視覺樹的根部開始(一般爲Window),並向下生成事件的控件。由於您的代碼將有機會在ListBoxItem之前處理事件,因此會被解僱(而不是處理),因此您的事件處理程序將被調用。您可以通過將您的示例中的MouseDoubleClickEvent替換爲PreviewMouseLeftButtonDown來實現此選項。

另一個選項是註冊一個類處理程序,當ListBoxItem觸發MouseLeftButtonDown事件時將會收到通知。這就像下面這樣:

EventManager.RegisterClassHandler(typeof(ListBoxItem), 
    ListBoxItem.MouseLeftButtonDownEvent, 
    new RoutedEventHandler(this.MouseLeftButtonDownClassHandler)); 

private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e) 
{ 
} 

類處理程序之前任何其他調用事件處理程序,但他們呼籲在整個應用程序指定類型的所有控件。所以如果你有兩個ListBoxes,那麼無論何時在任何一個點擊任何ListBoxItem,這個事件處理程序都會被調用。

至於第二個問題,要知道給定事件需要什麼類型的事件處理程序,並查看給定控件可用的事件列表,最好的方法是使用MSDN文檔。例如,由ListBoxItem處理的所有事件的列表爲http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem_events.aspx。如果您點擊某個事件的鏈接,則會包含該事件的事件處理程序的類型。

+1

Lord,這是一個很好的答案! – 2012-04-20 19:51:00

+1

有一件事,我想補充一點。不要使用ButtonDown事件。使用ButtonUp事件。只要你按下按鈕,應用程序就會很奇怪。它也有一個用戶交互的原因。在基本上所有流行的應用程序中,您可以在釋放按鈕之前通過移開鼠標來取消按鈕點擊。 – 2017-09-14 11:07:23

+0

@StefanFabian是的,但列表框中的項目通常會在mousedown上被選中。移走鼠標仍然可以工作。 – Wouter 2018-02-07 07:57:11

13

我認爲Andy使用PreviewMouseLeftButtonDown的第一個答案就是解決這個問題的方法。在XAML中它看起來像這樣:

<ListBox Name="testListBox"> 
    <ListBox.ItemContainerStyle> 
     <Style TargetType="{x:Type ListBoxItem}"> 
      <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown" /> 
     </Style> 
    </ListBox.ItemContainerStyle> 
</ListBox> 
8

還有一種方法可以在ListBox中獲取MouseDown事件。您可以添加事件處理程序,通過使用AddHandler方法handledEventsToo簽名處理,被標記的事件:

myListBox.AddHandler(UIElement.MouseDownEvent, 
     new MouseButtonEventHandler(ListBox_MouseDown), true); 

第三個參數上面是handledEventsToo這保證了它是否已經被標記爲Handled(此處理程序將被調用,不管其中ListBoxItem在列表框中)。
查看Marking Routed Events as Handled, and Class Handling的解釋。例如,
How to Attach to MouseDown Event on ListBox

9

也有另一種方式 - 來處理PreviewMouseDown事件,並檢查它是否是由該列表項觸發:

在XAML:

<ListBox PreviewMouseDown="PlaceholdersListBox_OnPreviewMouseDown"/> 

在代碼隱藏:

private void PlaceholdersListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    var item = ItemsControl.ContainerFromElement(sender as ListBox, e.OriginalSource as DependencyObject) as ListBoxItem; 
    if (item != null) 
    { 
     // ListBox item clicked - do some cool things here 
    } 
} 

受到this答案的啓發,但它使用名稱列表框,我建議使用發件人參數void不必要的依賴關係。

0

您可以使用SelectionChanged事件的SelectionChangedEventArgs參數來查找通過AddedItems和RemovedItems添加或刪除的項目,通常只有最新的點擊,或者如果沒有,則查看最後一個項目, 1。

相關問題