首页 文章

在不释放SelectedItem的情况下替换ListView的ItemsSource

提问于
浏览
1

我将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

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

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

相关问题