I have a ListBox
in my wpf window that binds to an ObervableCollection
. I want to open the browser if someone clicks on an element of the ListBox
(just like a link). Can someone tell me how to do this? I found something with listboxviews, does it only work this way or is there a way by just using the ListBox
?
Yours
Sebastian
You can add a style to ListBox.ItemContainerStyle, and add an EventSetter there:
<ListBox>
....
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
ListBoxItem_MouseDoubleClick is a method in your code behind with the correct signature for MouseDoubleClick.
I wanted to solve this without needing to handle the listBoxItem double click event in the code-behind, and I didn't want to have to override the listBoxItem style (or define the style to override in the first place). I wanted to just fire a command when the listBox was doubleclicked.
I created an attached property like so (the code is very specific, but you can generalise it as required):
public class ControlItemDoubleClick : DependencyObject {
public ControlItemDoubleClick()
{
}
public static readonly DependencyProperty ItemsDoubleClickProperty =
DependencyProperty.RegisterAttached("ItemsDoubleClick",
typeof(bool), typeof(Binding));
public static void SetItemsDoubleClick(ItemsControl element, bool value)
{
element.SetValue(ItemsDoubleClickProperty, value);
if (value)
{
element.PreviewMouseDoubleClick += new MouseButtonEventHandler(element_PreviewMouseDoubleClick);
}
}
static void element_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ItemsControl control = sender as ItemsControl;
foreach (InputBinding b in control.InputBindings)
{
if (!(b is MouseBinding))
{
continue;
}
if (b.Gesture != null
&& b.Gesture is MouseGesture
&& ((MouseGesture)b.Gesture).MouseAction == MouseAction.LeftDoubleClick
&& b.Command.CanExecute(null))
{
b.Command.Execute(null);
e.Handled = true;
}
}
}
public static bool GetItemsDoubleClick(ItemsControl element)
{
return (bool)element.GetValue(ItemsDoubleClickProperty);
}
}
I then declare my ListBox with the attached property and my target command:
<ListBox ItemsSource="{Binding SomeItems}"
myStuff:ControlItemDoubleClick.ItemsDoubleClick="true">
<ListBox.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="MyCommand"/>
</ListBox.InputBindings>
</ListBox>
Hope this helps.
I have updated AndrewS solution in order to solve the issue with firing executing the command if double click anywhere in the list box:
public class ControlDoubleClick : DependencyObject
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(ControlDoubleClick), new PropertyMetadata(OnChangedCommand));
public static ICommand GetCommand(Control target)
{
return (ICommand)target.GetValue(CommandProperty);
}
public static void SetCommand(Control target, ICommand value)
{
target.SetValue(CommandProperty, value);
}
private static void OnChangedCommand(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Control control = d as Control;
control.PreviewMouseDoubleClick += new MouseButtonEventHandler(Element_PreviewMouseDoubleClick);
}
private static void Element_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Control control = sender as Control;
ICommand command = GetCommand(control);
if (command.CanExecute(null))
{
command.Execute(null);
e.Handled = true;
}
}
}
And in the XAML the declaration for the ListBox is:
<ListBox ItemsSource="{Binding MyItemsSource, Mode=OneWay}">
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="behaviours:ControlDoubleClick.Command" Value="{Binding DataContext.MyCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
I Used Expression SDK 4.0
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick" SourceName="CaravanasListBox">
<i:InvokeCommandAction Command="{Binding AccionesToolbarCommand}" CommandParameter="{x:Static local:OpcionesBarra.MostrarDetalle}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Jaimir G.
Here's a behavior that gets that done on both ListBox
and ListView
. This is based of answers from Andrew S. and Vadim Tofan, great job guys!
public class ItemDoubleClickBehavior : Behavior<ListBox>
{
#region Properties
MouseButtonEventHandler Handler;
#endregion
#region Methods
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewMouseDoubleClick += Handler = (s, e) =>
{
e.Handled = true;
if (!(e.OriginalSource is DependencyObject source)) return;
ListBoxItem sourceItem = source is ListBoxItem ? (ListBoxItem)source :
source.FindParent<ListBoxItem>();
if (sourceItem == null) return;
foreach (var binding in AssociatedObject.InputBindings.OfType<MouseBinding>())
{
if (binding.MouseAction != MouseAction.LeftDoubleClick) continue;
ICommand command = binding.Command;
object parameter = binding.CommandParameter;
if (command.CanExecute(parameter))
command.Execute(parameter);
}
};
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewMouseDoubleClick -= Handler;
}
#endregion
}
Here's the extension class used to find the parent.
public static class UIHelper
{
public static T FindParent<T>(this DependencyObject child, bool debug = false) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
if (parentObject is T parent)
return parent;
else
return FindParent<T>(parentObject);
}
}
Usage:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:coreBehaviors="{{Your Behavior Namespace}}"
<ListView AllowDrop="True" ItemsSource="{Binding Data}">
<i:Interaction.Behaviors>
<coreBehaviors:ItemDoubleClickBehavior/>
</i:Interaction.Behaviors>
<ListBox.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding YourCommand}"/>
</ListBox.InputBindings>
</ListView>
来源:https://stackoverflow.com/questions/821564/double-click-a-listbox-item-to-open-a-browser