views:

2727

answers:

2

Hello,

I have a listbox in my wpf window that binds to an observable collection, now 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 lisbox?

Yours

Sebastian

+10  A: 

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.

Bob King
Thanks. This solves my problem too. One followup: This works great in the running application, but it hoses the visual studio designer (not a showstopper, but an irritation). I don't explicitly define a ListBoxItem style in the application resources, so the BasedOn will fail at design time. However, I have a theming library (WPFTheme) that defines this resource at runtime. If i do define a static resource, it obliterates the dynamic, themed one. Any thought on how I can make both play nice together?
ee
After a bit more experimentation, I figured it out...I just referenced the theme's xaml in a mergedresource property: <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Theme.xaml"/></ResourceDictionary.MergedDictionaries>
ee
This is pretty cool but what if you have already defined ItemContainerStyle in a ResourceDictionary?
Oliver
Just change to BasedOn="{StaticResource TheNameOfYourResource}" in the <Style> tag.
Bob King
@Bob +1 for an easy solution for the lack of a double click.
Metro Smurf
A: 

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.

AndrewS
but won't that fire if they double click on the scroll bar? Or any padding between ListBoxItems?
Bob King