[英]How to catch Click on ListboxItem when the item is templated?
I have a ListBox with ItemsTemplate set. 我有一个设置了ItemsTemplate的ListBox。
Now I want to catch Ctrl + Left click on a ListBoxItem. 现在,我想按Ctrl +在ListBoxItem上单击鼠标左键。
I found KeyBoard
class that should give me modifier keys. 我发现KeyBoard
类应该给我修饰键。 Now how do I get the click event on the ListBoxItem? 现在如何获取ListBoxItem上的click事件? Even better, how do I bind it to ICommand. 更好的是,如何将其绑定到ICommand。
I found some bits and pieces but don't know how to connect them. 我发现了一些点点滴滴,但不知道如何连接它们。 It seems InputBinding
seems could help me or EventSetter
. 看来InputBinding
似乎可以帮助我或EventSetter
。
Below is a simple example that handles Ctrl + PreviewMouseLeftButtonDown using an EventSetter in the ListBoxItem's Style. 下面是一个简单的示例,该示例使用ListBoxItem的Style中的EventSetter处理Ctrl + PreviewMouseLeftButtonDown。 This is probably what you want. 这可能就是您想要的。
XAML: 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>
Code-Behind: 代码隐藏:
void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
{
Console.WriteLine((sender as ListBoxItem).Content.ToString());
e.Handled = false;
}
}
To bind it to an ICommand, you can use an attached behavior like the EventToCommand behavior discussed here . 将其绑定到一个ICommand,你可以使用像讨论的EventToCommand行为的一个附加的行为在这里 。
EDIT: 编辑:
To address your comment, handling the Click-event will be a bit tricky for the ListBoxItem because of two things: 1) The ListBoxItem doesn't have a click event, and 2) The ListBoxItem internally handles some of the MouseEvents. 为了解决您的意见,处理ListBoxItem的Click事件会有些棘手,原因有两点:1)ListBoxItem没有click事件,并且2)ListBoxItem在内部处理某些MouseEvent。 Anyway, I came up with a simulated, attached ClickEvent to make it work. 无论如何,我想出了一个模拟的附加ClickEvent来使其工作。 See below. 见下文。 Hope it works. 希望它能工作。
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);
}
}
}
Sample usage is shown below. 用法示例如下所示。 I can't seem to set the attached event in XAML (I'm not sure why) so I had to do a workaround here. 我似乎无法在XAML中设置附加事件(我不确定为什么),所以我不得不在此处进行变通。 What I do is wait 'til the ListBoxItem gets loaded and Attach the event handler in the code-behind. 我要做的是等到ListBoxItem加载完毕并将事件处理程序附加到后面的代码中。
XAML: XAML:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="Loaded" Handler="OnLoaded"/>
</Style>
</ListBox.ItemContainerStyle>
...
</ListBox>
Code-Behind: 代码隐藏:
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!");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.