WPF Listbox binding

62,744

Solution 1

Mike, there are few problems with your bindings. Here's a complete sample demonstrating one way of doing what (I think) you're after.

View:

<Page.Resources>
    <ViewModel:Physician x:Key="physician"/>
</Page.Resources>
<StackPanel DataContext="{StaticResource physician}" >
    <TextBlock Text="{Binding Name}" Background="Orange"/>
    <TextBlock Text="Works in:"/>
    <ListBox ItemsSource="{Binding Clinics}" 
             SelectedValue="{Binding SelectedClinicId}" 
             SelectedValuePath="Id" DisplayMemberPath="Name" />
</StackPanel>

View model:

public class Physician
{
    private int _selectedClinicId;

    public Physician()
    {
        Name = "Overpaid consultant";
        Clinics = new ObservableCollection<Clinic>
                      {
                          new Clinic {Id = 0, Name = "Out Patients"},
                          new Clinic {Id = 1, Name = "ENT"},
                          new Clinic {Id = 2, Name = "GE"},
                      };
    }

    public string Name { get; set; }
    public IEnumerable<Clinic> Clinics { get; private set; }

    public int SelectedClinicId
    {
        get { return _selectedClinicId; }
        set
        {
            if (value != _selectedClinicId)
            {
                Debug.WriteLine(string.Format("setting clinic to: {0}",value));
                _selectedClinicId = value;
            }
        }
    }
}

public class Clinic
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Note that for read/write properties you would probably want to raise property change notifications.

Solution 2

Your issue is SelectedValue. At the ListBox level, binding to multiple selection objects is not supported. The only real way to do this with bindings would be to rework your ViewModel so that the list of clinics returned from the binding represents all clinics, and each object there should have an IsSelected (or something similar) property.

You can then use a style to handle the multi selection by adding this XAML within your ListBox node:

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

Solution 3

You are going to need to use a template with TextBox for name and ListBox for Clinics and you just bind the internal ListBox path to Clinics. DisplayMemberPath is a short cut a single TextBox. If you want more then you need individual controls.

Share:
62,744
Mike Malter
Author by

Mike Malter

My primary focus is as an independent contractor specializing in Microsoft technologies while seamlessly fitting in to fill a variety of roles from programming to Architect and Development Management. Specialties C#, VB.NET, SQL Server, SOA, WPF, PLINK (LINQ Parallel Processing), Team Foundation Server, ASP.NET., WCF, LINQ, Microsoft Networking Linked In Profile

Updated on January 12, 2020

Comments

  • Mike Malter
    Mike Malter over 4 years

    I have a physician object, and one of its properties is an ObservableList of clinics. It is being used in a window to show the details of a physician. I can get individual properties to bind to TextBox and ComboBox controls, but I can't get the list of clinics to bind to my ListBox.

    Here is the xaml for my ListBox:

    <ListBox Height="318" 
     HorizontalAlignment="Left" 
     Margin="422,0,0,0" 
     Name="lbClinic" 
     VerticalAlignment="Top" 
     Width="158" 
     SelectedValue="{Binding ClinicID, Path=Clinics, Mode=TwoWay, 
                              UpdateSourceTrigger = PropertyChanged}"
     SelectedValuePath="ClinicID" 
     DisplayMemberPath="Name"
     ItemsSource="{Binding DataContext.ClinicList, 
                              ElementName = PhysicianInfoLookup, Mode = OneWay}" 
     SelectionMode="Multiple" />
    

    The Listbox populates properly with items from the ClinicList which is a list of all possible clinics. However, I cannot get the Clinics list from the physician object to bind so that it's items are selected in the Listbox. I also want to go the other way and if an item is deselected, the ObservableList in the physician object will change accordingly.

    How do I two-way bind the ObservableList of Clinics in my physician object to the list of Clinics (ObservableList of clinic objects) in my Listbox?

    Thank you.

  • Mike Malter
    Mike Malter about 12 years
    Can you elaborate? I do appreciate your answer, but I'm not sure what it has to do with selecting items in a Listbox. Am I missing something? Thanks.
  • Phil
    Phil about 12 years
    What BalamBalam means is that the list box could be displaying more properties of a Clinic (Name, Address, Death rate? etc...). A list box in WPF is very flexible and can display almost anything using templates.
  • Mike Malter
    Mike Malter about 12 years
    I appreciate the extra thoughts, but don't need any of that. I am asking about how to bind a collection to a Listbox so that those items are selected and vice versa.
  • Mike Malter
    Mike Malter about 12 years
    Phil, thanks for taking the time to reply, but I'm a little lost with your answer, sorry. I have a full list of all clinics that the Listbox is populated with, and I want to highlight are the the ones that are in the list of clinics in the physician object. Also, if I select one not in the original list, I want it added, or if I deselect I want it removed from the physician's clinic list. This is probably one of those things that just can't be done with simple binding.