Связывание выбранных элементов ListBox - PullRequest
8 голосов
/ 29 апреля 2010

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

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

Где d - это какой-то ListBox из XAML.

Исключение:

Выбранный предмет не может быть привязан.

Почему?

Ответы [ 5 ]

8 голосов
/ 29 апреля 2010

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

В этом примере Windows DataContext был установлен себе (this) в своем конструкторе. Вы также можете легко вызвать логический уровень (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);
    }
}
3 голосов
/ 30 апреля 2010

Это рабочее решение, однако при изменении выбора 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();
         }
    }

}

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

myListBox.SelectionChanged += (s,e) => {
    BindingExpression be = 
         (BindingExpression) myListBox.GetBindingExpression(
                                      ListBox.SelectedItemsProperty);
    if(be!=null){
        bd.UpdateTarget();
    }
};
1 голос
/ 29 апреля 2010

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

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

d.SetBinding(ListBox.ItemsSourceProperty, new Binding { Source = MyOtherListbox.SelectedItems, Mode = BindingMode.OneWay});
1 голос
/ 29 апреля 2010

ListBox.SelectedItems только для чтения. Вы хотели связать с ListBox.SelectedItem вместо этого?

0 голосов
/ 23 января 2018

Мой трюк: в 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...