我有一個ListBox與ItemsTemplate設置。如何捕獲當項目模板化時單擊ListboxItem?
現在我想抓住Ctrl +左鍵單擊ListBoxItem。
我發現KeyBoard
類應該給我修飾鍵。現在我該如何獲得ListBoxItem上的點擊事件?更好的是,我如何將它綁定到ICommand。
我發現了一些碎片,但不知道如何連接它們。看來InputBinding
似乎可以幫助我或EventSetter
。
我有一個ListBox與ItemsTemplate設置。如何捕獲當項目模板化時單擊ListboxItem?
現在我想抓住Ctrl +左鍵單擊ListBoxItem。
我發現KeyBoard
類應該給我修飾鍵。現在我該如何獲得ListBoxItem上的點擊事件?更好的是,我如何將它綁定到ICommand。
我發現了一些碎片,但不知道如何連接它們。看來InputBinding
似乎可以幫助我或EventSetter
。
下面是一個簡單的例子,它使用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!");
}
}
的MouseLeftButtonDown是不是一個真正的點擊。 – Kugel 2010-10-20 20:54:20
你說得對。我只是認爲MouseDown會足夠好。無論如何,請參閱編輯。這是一個相當長的解決方案,但我希望它能起作用。 – ASanch 2010-10-20 21:52:10
謝謝你的洞察力。我從你的帖子中學到了很多東西。 – Kugel 2010-10-21 12:48:22