25

I have a WPF ListBox control and I'm setting its ItemsSource to a collection of item objects. How can I bind the IsSelected property of the ListBoxItem to a Selected property of a corresponding item object without having an instance of the object to set as a Binding.Source?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
BrandonS
  • 2,513
  • 7
  • 28
  • 29

2 Answers2

52

Just override ItemContainerStyle:

   <ListBox ItemsSource="...">
     <ListBox.ItemContainerStyle>
      <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" Value="{Binding Selected}"/>
      </Style>
     </ListBox.ItemContainerStyle>
    </ListBox>

Oh, by the way, I think you'd like this wonderful articles from dr.WPF: ItemsControl: A to Z.

Hope this helps.

Anvaka
  • 15,658
  • 2
  • 47
  • 56
  • 2
    Sadly this does not work with WinRT since [bindings are not supported on Setters](http://stackoverflow.com/a/11869065/641833). – Trisped May 15 '14 at 19:50
  • This doesn't seem to work *reliably* anymore. The binding only seems to get triggered when the items are in visible scope. I have a list of 100+ items, if I select all entries with CTRL+A, only the visible ones will have their **Selected** property set. Scrolling down fixes this. I guess this is a performance optimization of WPF, or possibly a bug. – UweB Nov 30 '20 at 12:44
  • For workarounds, I found the following helpful: see https://www.markwithall.com/programming/2017/05/14/accessing-wpf-listbox-selecteditems-using-mvvm.html near the bottom of the post. It's a feature, not a bug :) – UweB Nov 30 '20 at 12:56
3

I was looking for a solution in code, so here is the translation of that.

System.Windows.Controls.ListBox innerListBox = new System.Windows.Controls.ListBox();

//The source is a collection of my item objects.
innerListBox.ItemsSource = this.Manager.ItemManagers;

//Create a binding that we will add to a setter
System.Windows.Data.Binding binding = new System.Windows.Data.Binding();
//The path to the property on your object
binding.Path = new System.Windows.PropertyPath("Selected"); 
//I was in need of two way binding
binding.Mode = System.Windows.Data.BindingMode.TwoWay;

//Create a setter that we will add to a style
System.Windows.Setter setter = new System.Windows.Setter();
//The IsSelected DP is the property of interest on the ListBoxItem
setter.Property = System.Windows.Controls.ListBoxItem.IsSelectedProperty;
setter.Value = binding;

//Create a style
System.Windows.Style style = new System.Windows.Style();
style.TargetType = typeof(System.Windows.Controls.ListBoxItem);
style.Setters.Add(setter);

//Overwrite the current ItemContainerStyle of the ListBox with the new style 
innerListBox.ItemContainerStyle = style;
BrandonS
  • 2,513
  • 7
  • 28
  • 29
  • 4
    Hello BrandonS, Maybe both solutions work well, however when possible please prefer xml declarative approach to define UI behaviors. That way more people (Interaction devs, etc) can understand it and modify it easily. Regards, – wacdany Jul 09 '12 at 14:41