2010-10-20 94 views
2

我有一個ListBox與ItemsTemplate設置。如何捕獲當項目模板化時單擊ListboxItem?

現在我想抓住Ctrl +左鍵單擊ListBoxItem。

我發現KeyBoard類應該給我修飾鍵。現在我該如何獲得ListBoxItem上的點擊事件?更好的是,我如何將它綁定到ICommand。

我發現了一些碎片,但不知道如何連接它們。看來InputBinding似乎可以幫助我或EventSetter

回答

4

下面是一個簡單的例子,它使用ListBoxItem的樣式中的EventSetter處理Ctrl + PreviewMouseLeftButtonDown。這可能是你想要的。

XAML:

<ListBox> 
    <ListBox.ItemContainerStyle> 
     <Style TargetType="ListBoxItem"> 
      <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBoxItem_PreviewMouseLeftButtonDown"/> 
     </Style> 
    </ListBox.ItemContainerStyle> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <Button Content="{Binding}"/> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
    <s:String>Item1</s:String> 
    <s:String>Item2</s:String> 
    <s:String>Item3</s:String> 
    <s:String>Item4</s:String> 
</ListBox> 

代碼隱藏:

void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    if ((Keyboard.Modifiers & ModifierKeys.Control) > 0) 
    { 
     Console.WriteLine((sender as ListBoxItem).Content.ToString()); 
     e.Handled = false; 
    } 
} 

將其綁定到一個ICommand,您可以使用附加的行爲像EventToCommand行爲討論here

編輯:

爲了解決您的意見,處理點擊事件會有點棘手,因爲兩件事情ListBoxItem中:1)ListBoxItem中沒有一個點擊事件,和2) ListBoxItem在內部處理一些MouseEvent。無論如何,我想出了一個模擬的,附加的ClickEvent來使它工作。見下文。希望它有效。

public class AttachedEvents 
{ 
    private static readonly DependencyProperty IsTriggerEnabledProperty = 
     DependencyProperty.RegisterAttached("IsTriggerEnabled", typeof(bool), typeof(FrameworkElement), new FrameworkPropertyMetadata(false)); 

    public static readonly RoutedEvent ClickEvent; 

    static AttachedEvents() 
    { 
     try 
     { 
      ClickEvent = EventManager.RegisterRoutedEvent("Click", 
                 RoutingStrategy.Bubble, 
                 typeof(RoutedEventHandler), 
                 typeof(FrameworkElement)); 
     } 
     catch (Exception ex) 
     { } 
    } 


    private static void SetIsTriggerEnabled(FrameworkElement element, bool value) 
    { 
     if (element != null) 
     { 
      element.SetValue(IsTriggerEnabledProperty, value); 
     } 
    } 

    private static bool GetIsTriggerEnabled(FrameworkElement element) 
    { 
     return (element != null) ? (bool)element.GetValue(IsTriggerEnabledProperty) : false; 
    } 

    public static void AddClickHandler(DependencyObject o, RoutedEventHandler handler) 
    { 
     FrameworkElement element = (FrameworkElement)o; 
     element.AddHandler(ClickEvent, handler); 
     element.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonUp); 
     element.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonDown); 
    } 

    public static void RemoveClickHandler(DependencyObject o, RoutedEventHandler handler) 
    { 
     FrameworkElement element = (FrameworkElement)o; 
     element.RemoveHandler(ClickEvent, handler); 
     element.MouseLeftButtonUp -= new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonUp); 
     element.PreviewMouseLeftButtonDown -= new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonDown); 
    } 

    static void SimulatedClick_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     FrameworkElement element = (FrameworkElement)sender; 
     UpdateIsTriggerSet(element); 
     Mouse.Capture(element); 
    } 

    static void SimulatedClick_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     FrameworkElement element = (FrameworkElement)sender; 

     bool isTriggerSet = (bool)element.GetValue(IsTriggerEnabledProperty); 

     // update the trigger set flag 
     UpdateIsTriggerSet(element); 

     //release the mouse capture 
     Mouse.Capture(null); 

     // if trigger is set and we are still over the element then we fire the click event 
     if (isTriggerSet && IsMouseOver(element)) 
     { 
      element.RaiseEvent(new RoutedEventArgs(ClickEvent, sender)); 
     } 

    } 

    private static bool IsMouseOver(FrameworkElement element) 
    { 
     Point position = Mouse.PrimaryDevice.GetPosition(element); 
     if (((position.X >= 0.0) && (position.X <= element.ActualWidth)) && ((position.Y >= 0.0) && (position.Y <= element.ActualHeight))) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    private static void UpdateIsTriggerSet(FrameworkElement element) 
    { 
     Point position = Mouse.PrimaryDevice.GetPosition(element); 
     if (((position.X >= 0.0) && (position.X <= element.ActualWidth)) && ((position.Y >= 0.0) && (position.Y <= element.ActualHeight))) 
     { 
      if (!(bool)element.GetValue(IsTriggerEnabledProperty)) 
      { 
       element.SetValue(IsTriggerEnabledProperty, true); 
      } 
     } 
     else if ((bool)element.GetValue(IsTriggerEnabledProperty)) 
     { 
      element.SetValue(IsTriggerEnabledProperty, false); 
     } 
    } 
} 

示例用法如下所示。我似乎無法在XAML中設置附加事件(我不知道爲什麼),所以我不得不在這裏做一個解決方法。我所做的就是等待直到ListBoxItem被加載,然後在代碼隱藏中附加事件處理程序。

XAML:

<ListBox> 
    <ListBox.ItemContainerStyle> 
     <Style TargetType="ListBoxItem"> 
      <EventSetter Event="Loaded" Handler="OnLoaded"/> 
     </Style> 
    </ListBox.ItemContainerStyle> 
... 
</ListBox> 

代碼隱藏:

void OnLoaded(object sender, RoutedEventArgs e) 
{ 
    AttachedEvents.AddClickHandler((sender as ListBoxItem), HandleClick); 
} 

void HandleClick(object sender, RoutedEventArgs e) 
{ 
    if ((Keyboard.Modifiers & ModifierKeys.Control) > 0) 
    { 
     Console.WriteLine("Ctrl + Clicked!"); 
    } 
} 
+0

的MouseLeftButtonDown是不是一個真正的點擊。 – Kugel 2010-10-20 20:54:20

+0

你說得對。我只是認爲MouseDown會足夠好。無論如何,請參閱編輯。這是一個相當長的解決方案,但我希望它能起作用。 – ASanch 2010-10-20 21:52:10

+0

謝謝你的洞察力。我從你的帖子中學到了很多東西。 – Kugel 2010-10-21 12:48:22

相關問題