Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Listbox binding

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.

like image 698
Mike Malter Avatar asked Feb 20 '12 21:02

Mike Malter


People also ask

What is ItemsSource in WPF?

ItemsSource can be data bound to any sequence that implements the IEnumerable interface, although the type of collection used does determine the way in which the control is updated when items are added to or removed. When ItemsSource is set, the Items property cannot be used to control the displayed values.

What is TextBlock WPF?

The TextBlock control provides flexible text support for UI scenarios that do not require more than one paragraph of text. It supports a number of properties that enable precise control of presentation, such as FontFamily, FontSize, FontWeight, TextEffects, and TextWrapping.


2 Answers

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.

like image 121
Phil Avatar answered Oct 07 '22 23:10

Phil


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>
like image 33
Adam Robinson Avatar answered Oct 07 '22 22:10

Adam Robinson