locked
MVVM Multiselect ListBox SelectedItems Binding RRS feed

  • Question

  • Recently I started using MVVM to seperate my view code from my designer xaml, but this has implications for my CheckBoxList.

    Appaerently the SelectedItems (plural) property of the ListBox that contains my checkboxes is not a DependencyProperty and cannot be bound to.

    I cannot believe why Microsoft would do such a thing.
    What's the point of using MVVM when you can't bind to the most important properties of a control?

    I have found several solutions explaining it for WPF, but they use classes that don't exist in Silverlight, so I'm stuck again.
    I found solutions using attached properties. They compiled, but never showed the items as selected.
    Also I found an example where a guy gives his entire View to the ViewModel, so he can add the SelectedItems manually. That completely destroys the concept of Seperation of Concerns.

    Is there someone already using a multiselect ListBox with MVVM? Or is there an alternative where you can bind SelectedItems to? Maybe a DataGrid or something?

    Wednesday, September 8, 2010 5:04 AM

Answers

All replies

  • Hi,

    ListBox is not seal class, we could inherited from listbox and create SelectedItems DP. Check this sample:

    MVVMListBox:

        public class MVVMListBox:ListBox
        {
            public IList SelectedItems2
            {
                get { return (IList)GetValue(SelectedItems2Property); }
                set { SetValue(SelectedItems2Property, value); }
            }

            public static readonly DependencyProperty SelectedItems2Property =
                DependencyProperty.Register("SelectedItems2", typeof(IList), typeof(MVVMListBox),
                new PropertyMetadata(
                    new PropertyChangedCallback((s, e) =>
                        {

                        })));

            public MVVMListBox()
                : base()
            {
                this.SelectionChanged += delegate
                {
                    SelectedItems2 = SelectedItems;
                };
            }
        }

    Usage Sample:

    <Grid x:Name="LayoutRoot" Background="White">
            <StackPanel>
                <TextBlock Text="Items"/>
                <my:MVVMListBox ItemsSource="abcde" SelectionMode="Multiple" x:Name="mlb1"/>
                <TextBlock Text="Selected"/>
                <ListBox ItemsSource="{Binding Path=SelectedItems2,ElementName=mlb1}"/>
            </StackPanel>
        </Grid>

     

    Thanks,

    Friday, September 10, 2010 12:06 AM
  • I don't think I understand completely.

    Your solution uses two listboxes?

    I would like something where I could bind ItemsSource and SelectedItems to the same ListBox.
    I can't find where you would bind SelectedItems2 to SelectedItems internally. There's only the assignment on SelectionChanged.

    Is the following possible?

    XAML:

    <controls:MvvmListBox x:Name="PatientsListBox" ItemsSource="{Binding DataContext.Patients, ElementName=LayoutRoot}" SelectedItems2="{Binding DataContext.SelectedPatients, ElementName=LayoutRoot}" Style="{StaticResource CheckBoxList}" DisplayMemberPath="Name"/>
                      

    ViewModel:

    private EntitySet<Patient> _patients;
    private IEnumerable<Patient> _selectedPatients;

    public EntitySet<Patient> Patients
    {
        get
        {
            return _patients;
        }
        set
        {
            if (_patients != value)
            {
                _patients = value;
                OnNotifyPropertyChanged("Patients");
            }
        }
    }

    public IEnumerable<Patient> SelectedPatients
    {
        get
        {
            return _selectedPatients;
        }
        set
        {
            if (_selectedPatients != value)
            {
                _selectedPatients = value;
                OnNotifyPropertyChanged("SelectedPatients");
            }
        }
    }

    private void LoadPatients()
    {
         LoadOperation patientsLoadOperation = context.Load(context.GetPatientsQuery());
         patientsLoadOperation.Completed += new EventHandler(patientsLoadOperation_Completed);
    }

    void patientsLoadOperation_Completed(object sender, EventArgs e)
    {
          Patients = context.Patients;
    }

    private void GetSelectedPatients(Doctor doctor)
    {
        SelectedPatients = from pd in doctor.PatientDoctors
                            join p in Patients on pd.PatientSet_Id equals p.Id
                            select p;            
    }

    Friday, September 10, 2010 2:42 AM
  • I created a Microsoft bug request for this issue. Maybe they can provide us with a solution?

    https://connect.microsoft.com/VisualStudio/feedback/details/596732/binding-to-the-selecteditems-property-of-a-listbox-in-silverlight

    please vote for it :)

    Friday, September 10, 2010 4:12 AM