views:

411

answers:

5

I want to bind Listbox selectedItems to array. But .NET throw exceprion in runtime.

            d.SetBinding(ListBox.SelectedItemsProperty, new Binding { Source = SomeArray });

Where "d" some ListBox from XAML.

Exception: Selected Item cannot be bound. Why?

+1  A: 

ListBox.SelectedItems is read-only. Did you mean to bind to ListBox.SelectedItem instead?

wpfwannabe
No I have several selected items and I want to show them in ListBox in selected state
Polaris
Since that property is read-only, you can't use it for what you want. The only thing I can think of is to set individual `ListBoxItem.IsSelected` properties. If you insist on binding, the easiest path would be for you to create e.g. an attached SelectedItems `DependencyProperty` with custom logic in property changed event handler.
wpfwannabe
A: 

Hi Polaris...

I am not sure if I understand your question correctly or the exact scenario - but assuming you wanted to have one listbox "d" show the items that were selected in another listbox "MyOtherListbox" then you just need to set the binding mode to 'one way' else it will bring up an error.

You could do something like

d.SetBinding(ListBox.ItemsSourceProperty, new Binding { Source = MyOtherListbox.SelectedItems, Mode = BindingMode.OneWay});
Mark Pearl
I must use something Like this:d.SetBinding(ListBox.SelectedItemsProperty, new Binding { Source = SomeArray, Mode=OneWay });But it raise the same exception.
Polaris
No, you cannot bind to the SelectedItemsProperty since it only has a get accessor.I think the closest you will get to this is if you read the following thread...http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/f0183ef3-ee0e-4de9-86c7-73d2072baba7
Mark Pearl
great thread. It works as I expect.
Polaris
This will not refresh if selected items are changed, because SelectedItems is List and not an observable collection or binding list.
Akash Kava
Thanks Polaris - does that mean the thread answered your question?
Mark Pearl
+1  A: 

You can subscribe to the SelectionChanged event of the ListBox, and in the handler sync a collection of selected items.

In this example the Windows DataContext was set to itself (this) in its constructor. You could also easily call into a logic layer (ViewModel if you're using MVVM) from the event handler.

In Xaml:

<StackPanel>

    <ListBox
        ItemsSource="{Binding ListBoxItems}"
        SelectionMode="Multiple"
        SelectionChanged="ListBox_SelectionChanged">
    </ListBox>

    <ItemsControl
        ItemsSource="{Binding SelectedItems}">
    </ItemsControl>

</StackPanel>

And in the code-behind:

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    foreach (string item in e.RemovedItems)
    {
        SelectedItems.Remove(item);
    }

    foreach (string item in e.AddedItems)
    {
        SelectedItems.Add(item);
    }
}
omdsmr
A: 

Mark Pearl comment help me undesrtand this issue. I just need listbox.selectedItmes.add method. Thank everybody for help.

Polaris
No, you are not supposed to modify SelectedItems by yourself, that will do nothing as it will not refresh the bindings.
Akash Kava
A: 

This is the working solution, however when selection changes SelectedItemsProperty does not refresh bindings...

you can create a custom control as follow

public class MyListBox: ListBox{

    public MyListBox()
    { 
         this.SelectionChanged += (s,e)=>{ RefreshBindings(); };
    }

    private void RefreshBindings()
    {
         BindingExpression be = 
             (BindingExpression) GetBindingExpression(
                                      SelectedItemsProperty);
         if(be!=null){
               bd.UpdateTarget();
         }
    }

}

or in your app you can define event in every listbox as shown below ..

myListBox.SelectionChanged += (s,e) => {
    BindingExpression be = 
         (BindingExpression) myListBox.GetBindingExpression(
                                      ListBox.SelectedItemsProperty);
    if(be!=null){
        bd.UpdateTarget();
    }
};
Akash Kava