Привязка WPF IsSelected к ViewModel не устанавливает элементы, которые не были показаны в списке - PullRequest
5 голосов
/ 15 января 2010

У меня есть ViewModel, у которого есть свойство IsSelected, которое я связываю в своем ListView.ItemContainerStyle XAML со свойством IsSelected в моей модели представления.

Я вызываю приложение и заполняю коллекцию моделей представлений (которая показана на моем ListView) большим количеством элементов, скажем, около 2000. Затем я выбираю все в списке с помощью Ctrl-A . Элементы из коллекции моделей моего вида получают набор IsSelected только для элементов, видимых в ListView. Если я пролистываю список по списку, IsSelected устанавливается для всех отображаемых элементов. Если я пролистываю все элементы, то для всех элементов в моей модели представления свойство IsSelected имеет значение true.

Вот мой XAML для привязки IsSelected в виде списка к моей модели представления:

<ListView Margin="5" ItemsSource="{Binding FilteredComparisonList}" x:Name="comparisonListView">
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" />
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Source filename" DisplayMemberBinding="{Binding ImageFile.BaseFilename}" Width="Auto" />
        </GridView>
    </ListView.View>
</ListView>

Почему IsSelected для всех элементов модели моего представления не установлено в значение true, когда я выбираю все элементы в ListView?

Ответы [ 5 ]

4 голосов
/ 15 января 2010

MVVM может сделать это путем переопределения сочетания клавиш Ctrl-A с помощью собственной команды SelectAll (создайте команду SellectAll с помощью сочетания клавиш Ctrl-A). Реализация установит IsSelected на представлениях моделей.

Ваше свойство IsSelected в вашем представлении должно иметь двустороннюю привязку к вашей модели представления, чтобы элементы выглядели выделенными в вашем представлении.

Не думаю, что отключение виртуализации является необходимым.

Надеюсь, это поможет.

3 голосов
/ 15 января 2010

Это происходит из-за встроенной виртуализации ListView. Если вы не знакомы с этим, это означает, что элементы не становятся реальными, пока они не видны. Вы можете отключить виртуализацию ListView с помощью следующего свойства:

VirtualizingStackPanel.IsVirtualizing="False"

Но учтите, что это отрицательно скажется на производительности вашего ListView. Для 2000 предметов это не будет серьезным, но это может быть заметно.

2 голосов
/ 15 января 2010

ListBoxItem виртуализированы, они не существуют до тех пор, пока они не будут сгенерированы (когда они отображаются). Однако базовый ListView является производным от ListBox, который имеет свойство SelectedItems. SelectedItems - это список всех выбранных элементов, а не список выбранных ListBoxItems. Когда ListBoxItem отображается, его свойство IsSelected устанавливается в зависимости от того, находится ли его элемент (отображаемый элемент) в коллекции SelectedItems.

Это проблема для вашей модели представления, особенно если вам нужна виртуализация (что вы, вероятно, делаете для 2000 или около того элементов). Мне было бы интересно получить ответ на вопрос «Как связать свойство IsSelected моих моделей представления на основе того, находится ли элемент в коллекции SelectedItems ListBox?»

ответ, вероятно, включает конвертер

0 голосов
/ 08 апреля 2015

Я опубликую этот ответ, который нашел на другом форуме, поскольку он помог мне с этой проблемой.

Я определил интерфейс ISelectable для моих ViewModels для реализации

public interface ISelectable
{
    bool IsSelected { get; set; }
}

Затем в MyCustomListView я сделал это:

public class MyCustomListView : ListView
{
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        foreach (var item in e.AddedItems.OfType<ISelectable>())
            item.IsSelected = true;

        foreach (var item in e.RemovedItems.OfType<ISelectable>())
            item.IsSelected = false;

        base.OnSelectionChanged(e);
    }
}

Кроме того, вы можете подписаться на событие SelectionChanged объекта ListView и использовать тот же код, что и выше.

0 голосов
/ 19 февраля 2013

У меня была такая же проблема, и вот что мне наконец помогло:

Положите в ListView:

VirtualizingStackPanel.VirtualizationMode="Standard"
...