2010-04-29 4 views
8

Я хочу привязать Listbox selectedItems к массиву. Но .NET запускает исключение во время выполнения.ListBox SelectedItems Binding

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

Где d некоторые ListBox из XAML.

Исключение:

Выбранный элемент не может быть связано.

Почему?

ответ

1

ListBox.SelectedItems предназначен только для чтения. Вы имели в виду привязку к ListBox.SelectedItem?

+0

Нет У меня есть несколько выбранных элементов, и я хочу, чтобы показать их в ListBox в выбранном состоянии – Polaris

+1

Поскольку это свойство только для чтения, вы не можете использовать его за то, что хотеть. Единственное, о чем я могу думать, это установить отдельные свойства ListBoxItem.IsSelected. Если вы настаиваете на привязке, самый простой путь - создать для вас, например. прикрепленный SelectedItems 'DependencyProperty' с настраиваемой логикой в ​​обработчике обработчика свойства. – wpfwannabe

1

Я не уверен, правильно ли я понял ваш вопрос или точный сценарий - но если вы хотите, чтобы один список «d» отображал элементы, которые были выбраны в другом списке «MyOtherListbox», вам просто нужно установить привязку mode to 'one way', иначе это вызовет ошибку.

Вы могли бы сделать что-то вроде

d.SetBinding(ListBox.ItemsSourceProperty, new Binding { Source = MyOtherListbox.SelectedItems, Mode = BindingMode.OneWay}); 
+0

Я должен использовать что-то Пример: d.SetBinding (ListBox.SelectedItemsProperty, новое связывание {Source = SomeArray, Mode = OneWay}); Но это вызывает то же исключение. – Polaris

+1

Нет, вы не можете привязываться к элементу SelectedItemsProperty, поскольку он имеет доступ только для доступа. Я думаю, что ближе всего вы доберетесь до этого, если прочитаете следующую тему ... http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/f0183ef3-ee0e-4de9 -86c7-73d2072baba7 –

+0

отличная тема. Он работает, как я ожидаю. – Polaris

7

Вы можете подписаться на событие SelectionChanged в ListBox, и в обработчике синхронизации набор выбранных элементов.

В этом примере Windows DataContext был установлен в его конструктор (он). Вы также можете легко вызвать логический уровень (ViewModel, если вы используете MVVM) из обработчика событий.

В Xaml:

<StackPanel> 

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

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

</StackPanel> 

И фоновый код:

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); 
    } 
} 
+2

Это похоже на привязку OneWayToSource. Если я изменил коллекцию SelectedItems, изменения не будут отображаться в списке. –

+1

@BogdanVerbenets Может быть, режим Mode для TwoWay и UpdateSourceTrigger для PropertyChanged сделает трюк? Кстати, у нас одно и то же имя! : D –

+2

Downvoted, потому что предложение использования обработчика события в коде для вызова в модель просмотра не следует шаблону MVVM. Если вы не против кодового кода (и я не против этого, но что бы то ни было), используйте это. Но, пожалуйста, не загрязняйте модели просмотра, вызывая их из кода. – aaronburro

3

Это рабочий раствор, однако при выборе для изменения SelectedItemsProperty не обновляется привязок ...

вы можете создать настраиваемое управление, как показано ниже:

public class MyListBox: ListBox{ 

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

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

} 

или в вашем приложении вы можете определить событие в каждом ListBox, как показано ниже ..

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

спасибо. я добавил обходное решение в своем ответе – dovid

0

мой трюк: в XAML, используйте MultiBinding, силу выполнить преобразователь в Count изменения свойств (это работает!).

<MultiBinding Converter="{StaticResource SelectedRowsTotal }"> 
    <Binding Path="SelectedItems" ElementName="listBox1" /> 
    <Binding Path="SelectedItems.Count" ElementName="listBox1" /> 
</MultiBinding> 

Преобразователь:

public class SelectedRowsTotal : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var selecteds = values as IEnumerable; 

     if (selected == null) 
      return null; 

     return selecteds.Cast<SomeType>().Sum(x=> x.SomeProperty) = total; 
    } 

    object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     return null; 
    } 
}