在不丢失SelectedItem的情况下替换ListView ItemsSource

时间:2010-08-12 20:01:45

标签: c# data-binding listview collections service

我将ListView数据绑定到来自服务层的集合。响应事件,与​​ListView关联的视图模型刷新ListView的数据。为了检索更新的数据,vm从服务层检索新的集合实例。此集合中的项目为Equals(),但不包括ReferenceEquals()与先前返回的集合中的等效项目。

您是否可以推荐一种方法,避免以下方法的缺点,同时仍允许vm将此数据插入ListView而不会导致ListView丢失其SelectedItem?

谢谢你,


一种简单的方法(视图模型代码; ListView的SelectedItem& ItemsSource绑定到vm上的相同绑定属性):

var selectedItem = SelectedItem;
ItemsSource = service.GetData();
SelectedItem = Accounts.SingleOrDefault(x => x.Equals(selectedItem));

这种做法看起来很难看。它还涉及重置SelectedItem - 如果更改SelectedItem会更改主详细信息表单上的详细信息编辑,则可能会出现问题。 (ItemsSource的设置导致SelectedItem被清除,这就是它在最后一行重新设置的原因。)

另一种方法是编写一个加载ObservableCollection<>的适配器。代理对象指向从初始服务层调用返回的数据。无论何时从服务层检索更新的数据,都会更新代理对象以指向新检索的对象。这样,ListView的ItemsSource不需要重置来更新ListView(它保持绑定到相同的ObservableCollection<>),这意味着SelectedItem不会被重置。这种方法的缺点是涉及的代码量。

2 个答案:

答案 0 :(得分:0)

嗯......那怎么样:

在ListView上注册SelectionChanged和DataContextChanged的事件处理程序:

<ListView Name="listView" SelectionChanged="listView_SelectionChanged" DataContextChanged="listView_DataContextChanged" />

在SelectionChanged处理程序中,将SelectedItem保存在ListView的Tag中

private void listView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    (sender as ListView).Tag = (sender as ListView).SelectedItem;
}

一旦ListView的DataContext发生更改,请根据新集合计算标记中保存的最后一个SelectedItem,并从该集合中设置新项目:

    private void listView_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        List<CustomClass> newList = e.NewValue as List<CustomClass>;
        if (newList != null && (sender as ListView).Tag != null)
        {
            foreach (CustomClass cClass in newList)
                if (cClass.Equals((sender as ListView).Tag as CustomClass))
                    (sender as ListView).SelectedItem = cClass;
        }
    }

答案 1 :(得分:0)

我最终编写了映射器代码,该代码加载了一个ObservableCollection,代理对象指向从服务层检索到的真实对象。每次从服务层获取更新时,映射器代码都会根据需要添加/删除/更新代理对象。