选择到ViewModel的WPF绑定不会设置未在列表中显示的项目

时间:2010-01-14 22:50:12

标签: wpf data-binding listview binding mvvm

我有一个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中的所有项目时,为什么ListView我的视图模型中的所有项目都设置为无效?

5 个答案:

答案 0 :(得分:4)

MVVM方法是使用您自己的SelectAll命令覆盖Ctrl-A快捷方式(使用快捷键Ctrl-A创建SellectAll命令)。实现将在视图模型上设置IsSelected。

视图中的IsSelected属性需要与视图模型进行双向绑定,以便在视图中显示选中的项目。

我不认为关闭虚拟化是必要的。

希望这有帮助。

答案 1 :(得分:3)

由于ListView的内置虚拟化,这种情况正在发生。如果你不熟悉它,它的基本含义是物品在它们可见之前不会变成现实。您可以使用以下属性关闭ListView的虚拟化:

VirtualizingStackPanel.IsVirtualizing="False"

但请注意,这会对ListView的性能产生负面影响。对于2,000件物品,它不会很严重,但可能会很明显。

答案 2 :(得分:2)

ListBoxItem是虚拟化的,它们在生成之前不存在(当它们被带入视图时)。但是,底层ListView派生自ListBox,它具有SelectedItems属性。 SelectedItems是所有选定项目的列表,而不是所选ListBoxItems的列表。当ListBoxItem进入视图时,它的IsSelected属性是根据它的项目(它显示的项目)是否在SelectedItems集合中设置的。

这是您的视图模型的一个问题,特别是如果您需要启用虚拟化(您可能需要2000个左右的项目)。我会对“如何根据项目是否在ListBox的SelectedItems集合中绑定我的视图模型IsSelected属性?”这个问题的答案感兴趣。

答案可能涉及转换器

答案 3 :(得分:0)

我遇到了同样的问题,这最终帮助了我:

加入ListView

VirtualizingStackPanel.VirtualizationMode="Standard"

答案 4 :(得分:0)

我发布了我在其他论坛上发现的答案,因为它帮助我解决了这个问题。

我已经为我的ViewModel定义了一个可选的接口来实现

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

或者,您可以订阅ListView的SelectionChanged事件并使用上面相同的代码。

相关问题