Вопрос

Я реализовал шаблон выбора, подобный тому, который описан в этот пост использование ViewModel для хранения IsSelected значения и путем привязки ListViewItem.IsSelected к выбранной ViewModel:

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
    </Style>
</ListView.ItemContainerStyle>

В целом это работает, но я сталкиваюсь с серьезной проблемой.Используя a VirtualizingStackPanel как панель в виде списка, только видимый ListViewItem создаются.Если я использую "Ctrl + A" для выбора всех элементов или с помощью комбинации клавиш, такой как "Shift + Ctrl + End" для первого элемента, все элементы будут выбраны, но для невидимых элементов ViewModel не получит значение IsSelected, равное true.Это логично, потому что если ListViewItem не созданы, привязка не может работать.

Кто-нибудь сталкивался с такой же проблемой и нашел решение (помимо отказа от использования VirtualizingStackPanel)?

Это было полезно?

Решение

Я нашел другой способ обработки выбора в шаблоне MVVM, который решил мою проблему.Вместо сохранения выделения в viewmodel, выделение извлекается из ListView / ListBox и передается в качестве параметра Команде.Все сделано в XAML:

<ListView 
    x:Name="_items"
    ItemsSource="{Binding Items}" ... />

<Button 
    Content="Remove Selected" 
    Command="{Binding RemoveSelectedItemsCommand}" 
    CommandParameter="{Binding ElementName=_items, Path=SelectedItems}"/>

на мой взгляд, модель:

private void RemoveSelection(object parameter)
{
    IList selection = (IList)parameter;
    ...
}

Другие советы

В моем случае я решил эту проблему, создав класс ListBoxEx из ListBox и добавив код для реагирования на изменения выбора, применяя состояние выбора к моделям представления элементов:

private readonly List<IListItemViewModelBase> selectedItems = new List<IListItemViewModelBase>();

protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
    base.OnSelectionChanged(e);

    bool isVirtualizing = VirtualizingStackPanel.GetIsVirtualizing(this);
    bool isMultiSelect = (SelectionMode != SelectionMode.Single);

    if (isVirtualizing && isMultiSelect)
    {
        var newSelectedItems = SelectedItems.Cast<IListItemViewModelBase>();

        foreach (var deselectedItem in this.selectedItems.Except(newSelectedItems))
        {
            deselectedItem.IsSelected = false;
        }

        this.selectedItems.Clear();
        this.selectedItems.AddRange(newSelectedItems);

        foreach (var newlySelectedItem in this.selectedItems)
        {
            newlySelectedItem.IsSelected = true;
        }
    }
}

Помимо того, что вы не используете VirtualizingStackPanel, единственное, о чем я могу думать, это захватить эти сочетания клавиш и иметь методы для изменения определенного диапазона ваших ViewModel предметы, чтобы их IsSelected свойство установлено в True (например,, SelectAll(), SelectFromCurrentToEnd()).В основном в обход Binding на ListViewItem для контроля отбора в таких случаях.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top