创建一个新的有序ObservableCollection

时间:2013-11-18 11:21:39

标签: c# mvvm combobox observablecollection

我有ObservableCollection定义如下:

public class ResourceList : ObservableCollection<Resource>
{
    public ResourceList() : base()
    {
    }
}

public class Resource : INotifyPropertyChanged
{
    public Resource()
    {
        Name = "";
        UserName = "";
        EMail = "";
        Date = "";
        Time = "";
        SWList = new ObservableCollection<string>();
    }
    ...

我想排序我的上述集合的实例,如下所示:

ResourceList = from resource in ResourceList
               orderby resource.Name descending
               select resource;

然而这不起作用!我究竟做错了什么?请正确解释,因为我是C#和MVVM-concept的新手!

3 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。但是您需要更新绑定集合本身而不是更改集合引用。

快速而肮脏的解决方案是:

ResourceList.Clear();
ResourceList.AddRange(from resource in ResourceList
               orderby resource.Name descending
               select resource);

其中AddRange可以是ObservableCollection<T>上的扩展方法,实际上将IEnumerable添加到集合中,因为(ObservableCollection没有AddRange()类似于List.AddRange())。帮助AddRange

我认为第二种解决方案,但我不确定:是在NotifyPropertyChanged属性上引发ResourceList事件。

E.g。

class SomeViewModel : INotifyPropertyChanged
{

   public ObservableCollection<Resource> ResourceList{
    get{ return value; }
    set
    { 
      _resourceList = value ;
      OnPropertyChanged("ResourceList");
    } 

  }
}

答案 1 :(得分:0)

对它进行排序,只需将其发送到列表中即可。

ResourceList = from resource in ResourceList
           orderby resource.Name descending
           select resource).ToList();

答案 2 :(得分:0)

我知道其中一些优秀的用户已经发布了有效的解决方案,但我还想指出你可以选择的替代方案。

1)首先,如果您不需要对ResourceList进行排序,您可以直接在View中进行排序。以下是适用于您的上下文的粗略示例:

// Add this at the top
// xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
<UserControl.Resources>
    <CollectionViewSource x:Key="ResourceListViewSource"
                          Source="{Binding ResourceList}">
        <CollectionViewSource.SortDescriptions>
            <cm:SortDescription PropertyName="{Binding Name}"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
</UserControl.Resources>

请注意,您需要向ComponentModel添加命名空间以及对WindowsBase dll的引用。 然后像这样使用它:

ItemsSource="{Binding Source={StaticResource ResourceListViewSource}}"

2)如果您仍然想使用LINQ,Lews Therin建议的方法会做(做一个扩展方法),但是例如简单地分配它会起作用:

ResourceList = new ObservableCollection<Resource>(from resource in ResourceList orderby resource.Name descending select resource);

因为构造函数可以接受它。请注意,在这种情况下,您需要手动调用PropertyChanged上的ObservableCollection事件(在set内将是最佳位置或至少在排序逻辑之后直接),否则您的视图将不会收到有关更改的通知。

以下是PropertyChanged事件所需的处理程序代码:

public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(string propertyName)
{
    var propertyChanged = PropertyChanged;
    if (propertyChanged != null)
        propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

在一天结束时,您始终可以将已排序的列表输出到隐式类型的局部变量中并从那里获取。

希望这有帮助。

P.S。如果您仍然想知道如何将排序扩展方法发送到ObservableCollection让我知道,我可以提供一些示例。