ListCollectionView的实时整形错误

时间:2015-11-03 11:47:07

标签: wpf sorting dynamic

深入挖掘后,为什么现场整形,详细按名称自动排序组,是行不通的,我决定写一个小测试应用程序,解决方案下载在这里:

here

下面是对问题的描述:我使用了Person对象的ObservableCollection,其中包含Age和Name属性(使用NPC)。我使用自定义GroupStyle创建一个绑定到DataGrid的ListCollectionView来公开Expander

对于这个视图,我设置了:

  • GroupDescription to Age
  • SortDescription to Age(对组进行排序)
  • SortDescription to Name

启动后,DispatcherTimer会将每个人的所有年龄重新计算为30到45之间的随机值。

在运行时故障:对于组的所有动态度假村的约60-70%,排序顺序是正确的,例如例如31之前的34之前的41之前的45。但是有时候第30个数字在两个第40个数字之间,这是错误的。问题在哪里,我该如何解决?顺便说一下,问题只发生在群组排序上。

BTW:为了LiveSortingProperties集合的用途,设置SortDescription和IsLiveSorting = True显然会激活实时整形,在这种情况下我应该在这个集合中添加一个字符串?

以下是错误的群组排序的屏幕截图:

Example Picture of wrong sorting

enter image description here

3 个答案:

答案 0 :(得分:1)

按发现顺序列出群组。在您的情况下,数据按年龄(然后按名称)排序,因此数据的初始扫描将在Age-34组之前发现Age-31组。但是,如果没有人的年龄= 37岁,则没有Age-37组。稍后,如果使用Age = 37添加新Person(或更改现有Person的Age,启用Live-Grouping),则会创建一个新的Age-37组。但由于它是在初始组之后发现的,因此会在所有这些组之后添加。

目前(4.6.1)无法为组本身声明排序顺序。我们正在考虑添加此功能,正如许多人所要求的那样。

BTW:LiveSortingProperties的目的是针对您希望按属性A,B和C排序的情况,但您知道只有属性C会发生变化。在SortDescriptions中声明所有三个属性,但在LiveSortingProperties中仅声明C。这样我们就不会浪费精力为A和B设置永远不会被调用的更改侦听器。

答案 1 :(得分:1)

我最近遇到了这个问题。因为我的客户可能不会立即升级到4.6.2我创建了一个解决方案。

我的应用程序使用ReactiveUI(http://reactiveui.net/)来促进此解决方案。使我的解决方案适应您的Person示例,基本上我监视Age属性的任何更改,然后计算组的数量(即年龄),并且只有当年龄组的数量发生变化时(DistinctUntilChanged)我才重新配置分组和排序。

因为它使用了反应模式,所以非常有效,但在我的情况下,任何时候都只有几十个元素。

// NB People is a ReactiveList<Person>

void SetupInterface()
{
    People.ItemChanged.Select(p => p.PropertyName == "Age")
        .Where(ageChanged => ageChanged)
        .DistinctUntilChanged(_ => People.GroupBy(x => x.Age).Count())
        .Subscribe(_ =>
        {
            ConfigureGrouping();
        });
    ConfigureGrouping();
}

void ConfigureGrouping()
{
    using (_collectionView.DeferRefresh())
    {
        // code to reset and rebuild the group and sort descriptions...
    }
}

答案 2 :(得分:0)

 Random rnd = new Random();
 DispatcherTimer timer = new DispatcherTimer();
 timer.Interval = TimeSpan.FromMilliseconds(4000);
 timer.Tick += (sender, args) =>
 {
      foreach (var person in Persons)
      {
           person.Age = rnd.Next(30, 45);
       }
       PersonsView.Refresh();
  };
  timer.IsEnabled = true;

View.Refresh为我做了伎俩