使用ItemsSource绑定ListView时,向ListView指示是否已选择一个或多个项目的正确方法是什么?

时间:2015-10-05 18:21:14

标签: wpf listview

我有一个WPF表单,其中包含一个ListView和以下绑定:

    <ListView ItemsSource="{Binding SelectableItems}" SelectionMode="Extended">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="IsSelected" Value="{Binding IsSelected}" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Data From" DisplayMemberBinding="{Binding Started}" Width="150" />
                <GridViewColumn Header="Data To" DisplayMemberBinding="{Binding Finished}" Width="150" />
            </GridView>
        </ListView.View>
    </ListView>

ViewModel的SelectableItems属性返回SelectableObject项的ObservableCollection,其中SelectableObject继承自ListViewItem。

我们面临的挑战如下。初始化视图时,SelectableItems集合中的一个或多个项可能将其IsSelected属性设置为true。显示视图时,视觉上每个项目看起来都处于正确的选择状态。不幸的是,似乎“当前选择”信息没有完全传达给ListView本身。在对未选择的项目执行简单单击时的预期操作是取消选择任何当前选择的项目,然后单击的项目将成为IsSelected设置为true的唯一项目。这似乎没有发生。而是将新单击的项目添加到先前单击的项目集中...但仅限第一次。所有后续单击操作均按预期运行。

在初始化期间是否还需要做其他事情以正确初始化ListView对当前所选项目的期望?

2 个答案:

答案 0 :(得分:1)

基本上,ListView使用SelectedItems属性来跟踪扩展选择。当您的集合绑定到控件时,它无法知道/更新SelectedItems集合,因此不知道有选择的对象。不幸的是,SelectedItems属性不可绑定。

我过去创建了附加属性,用可绑定属性“包装”SelectedItems集合,但它很麻烦,而且我很确定我的实现可能会导致泄漏。

或者,您可以使用一些次要的代码隐藏/附加属性在SelectedItems更改时设置ItemsSource属性:

修改:已更改为附加财产

public class Bindable
{
    public static readonly DependencyProperty InitializeSelectedItemsProperty = DependencyProperty.RegisterAttached(
                                                            "InitializeSelectedItems", typeof(bool), typeof(Bindable), new PropertyMetadata(default(bool), InitializeSelectedItemsChanged));

    private static void InitializeSelectedItemsChanged(DependencyObject depObject, DependencyPropertyChangedEventArgs args)
    {
        var listView = depObject as ListBox;

        if (listView != null && (bool)args.NewValue)
        {
            TypeDescriptor.GetProperties(listView)["ItemsSource"]
                    .AddValueChanged(listView, new EventHandler(ListViewItemsSourceChanged));
        }
    }

    private static void ListViewItemsSourceChanged(object sender, EventArgs eventArgs)
    {
        var listView = sender as ListBox;

        listView.SelectedItems.Clear();

        foreach (var item in listView.ItemsSource.OfType<ISelectable>().Where(i => i.IsSelected))
        {
            listView.SelectedItems.Add(item);
        }
    }
}

<ListView ItemsSource="{Binding SelectableItems}" Bindable.InitializeSelectedItems="True" SelectionMode="Extended" ...>

答案 1 :(得分:0)

如果您的列表视图是可以标识为一对键/值的项目列表,则解决方案是将所选项目存储在列表中,或者更好地存储在词典中。

然后当你的列表被绑定更新时,你应该遍历你的字典并测试listview中是否存在一对键/值,如果true set是${applicationId}的属性。

这是一种方式。