Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带有基类型的ObservableCollection的自定义排序_C#_Sorting_Observablecollection - Fatal编程技术网

C# 带有基类型的ObservableCollection的自定义排序

C# 带有基类型的ObservableCollection的自定义排序,c#,sorting,observablecollection,C#,Sorting,Observablecollection,我有以下简化课程: public class BaseContainer { public BaseContainer() { Children = new ObservableCollection<BaseContainer>(); } public ObservableCollection<BaseContainer> Children { get; set; } } public class ItemA : Base

我有以下简化课程:

public class BaseContainer
{
    public BaseContainer()
    {
        Children = new ObservableCollection<BaseContainer>();
    }
    public ObservableCollection<BaseContainer> Children { get; set; }
}

public class ItemA : BaseContainer
{
    public ItemA()
    {
        base.Children.Add(new ItemB() { ItemBName = "bb" });
        base.Children.Add(new ItemA() { ItemAName = "ab" });
        base.Children.Add(new ItemB() { ItemBName = "ba" });
        base.Children.Add(new ItemA() { ItemAName = "aa" });
    }
    public string ItemAName { get; set; }
}

public class ItemB : BaseContainer
{
    public string ItemBName { get; set; }
}
我正在尝试根据两个条件对ItemA.Children集合进行排序:

所有项目A必须在集合中排在第一位 项目A应按项目名称排序 项目B应按项目名称排序 所以在分类之后,我会期待这样的事情:

var result = base.Children
    .OrderBy(b => b.GetType().Name)
    .ThenBy(b => b.ItemName);
ItemA-ItemAName=aa ItemA-ItemAName=ab ItemB-ItemBName=ba ItemB-ItemBName=bb 关于如何实现这一点有什么想法吗

我可以按类类型名称进行排序:

        List<BaseContainer> temp = base.Children.ToList();
        temp.Sort((x, y) => string.Compare(x.GetType().Name, y.GetType().Name));
        base.Children.Clear();
        base.Children.AddRange(temp);
但是名字没有排序


谢谢

这将获得所有A,按AName订购,然后按B名称订购所有B

var result = temp.OrderBy(x => x.GetType().Name).ThenBy(x => GetPropValue(x));

string GetPropValue(object o)
{
    Type t = o.GetType();
    var p = t.GetProperty("ItemAName");
    if (p != null)
    {
        return (string)p.GetValue(o, null);
    }
    p = t.GetProperty("ItemBName");
    return (string)p.GetValue(o, null);
}
var result = Children.OfType<ItemA>().OrderBy(a => a.ItemAName).Cast<Base>()
    .Concat(Children.OfType<ItemB>().OrderBy(b => b.ItemBName));

我不确定这是不是我会选择的设计。。。您可以考虑添加一些基类来促进这种排序。

< P>这将得到所有的A,用AName排序,然后用B名称排序所有的B。p>
var result = Children.OfType<ItemA>().OrderBy(a => a.ItemAName).Cast<Base>()
    .Concat(Children.OfType<ItemB>().OrderBy(b => b.ItemBName));

我不确定这是不是我会选择的设计。。。您可以考虑添加一些基类来促进这种排序。

< P>您通过指定ItMeN名字初始化这些项,但是BaseCeNeReor、ItMeA和ItMeb都没有定义这样的属性。 在基本类BaseContainer“”中声明ItemName。项目类自动继承此属性,不需要在其中重新定义此类字段

public class BaseContainer
{
    public string ItemName { get; set; }

    ...
}

public class ItemA : BaseContainer
{
    // Inherits ItemName 
}

public class ItemB : BaseContainer
{
    // Inherits ItemName 
}
现在按如下方式对列表进行排序:

var result = base.Children
    .OrderBy(b => b.GetType().Name)
    .ThenBy(b => b.ItemName);
在排序之前,不需要将其存储到临时列表中。结果是一个IEnumerable。如果要将结果存储为列表,可以附加.ToList

var result = base.Children
    .OrderBy(b => b.GetType().Name)
    .ThenBy(b => b.ItemName)
    .ToList();
更新

根据您的评论,您没有公共ItemName属性。为什么?你真的应该有一个。重构你的类。如果出于某种原因,您不想在BaseContainer中使用ItemName,请创建一个抽象基类项,或者让这些项实现一个公共接口

public abstract class Item : BaseContainer
{
    public string ItemName { get; set; }
}

public class ItemA : Item
{
}

public class ItemB : Item
{
}

现在你可以这样分类了

var result = base.Children
    .OfType<Item> // or .OfType<IItem>
    .OrderBy(i => i.GetType().Name)
    .ThenBy(i => i.ItemName);
这简化了排序,因为按类型排序和按名称排序都可以在一个步骤中完成。此字符串也将显示在列表框、组合框等中

var result = base.Children
    .OrderBy(b => b.ToString());
如果不可能,请为此目的创建并实现一个接口:

public interface ISortable
{
    string SortString { get; }
}

public class ItemA : BaseContainer, ISortable
{
    public string ItemAName { get; set; }

    public string SortString { get { return "ItemA: " + ItemAName; } }
}
和排序

var result = base.Children
    .OfType<ISortable> 
    .OrderBy(b => b.SortString);

您可以通过指定ItemName来初始化项,但BaseContainer、ItemA和ItemB都没有定义这样的属性

在基本类BaseContainer“”中声明ItemName。项目类自动继承此属性,不需要在其中重新定义此类字段

public class BaseContainer
{
    public string ItemName { get; set; }

    ...
}

public class ItemA : BaseContainer
{
    // Inherits ItemName 
}

public class ItemB : BaseContainer
{
    // Inherits ItemName 
}
现在按如下方式对列表进行排序:

var result = base.Children
    .OrderBy(b => b.GetType().Name)
    .ThenBy(b => b.ItemName);
在排序之前,不需要将其存储到临时列表中。结果是一个IEnumerable。如果要将结果存储为列表,可以附加.ToList

var result = base.Children
    .OrderBy(b => b.GetType().Name)
    .ThenBy(b => b.ItemName)
    .ToList();
更新

根据您的评论,您没有公共ItemName属性。为什么?你真的应该有一个。重构你的类。如果出于某种原因,您不想在BaseContainer中使用ItemName,请创建一个抽象基类项,或者让这些项实现一个公共接口

public abstract class Item : BaseContainer
{
    public string ItemName { get; set; }
}

public class ItemA : Item
{
}

public class ItemB : Item
{
}

现在你可以这样分类了

var result = base.Children
    .OfType<Item> // or .OfType<IItem>
    .OrderBy(i => i.GetType().Name)
    .ThenBy(i => i.ItemName);
这简化了排序,因为按类型排序和按名称排序都可以在一个步骤中完成。此字符串也将显示在列表框、组合框等中

var result = base.Children
    .OrderBy(b => b.ToString());
如果不可能,请为此目的创建并实现一个接口:

public interface ISortable
{
    string SortString { get; }
}

public class ItemA : BaseContainer, ISortable
{
    public string ItemAName { get; set; }

    public string SortString { get { return "ItemA: " + ItemAName; } }
}
和排序

var result = base.Children
    .OfType<ISortable> 
    .OrderBy(b => b.SortString);

我想到了这一点,但对我来说不起作用。项目A和项目B不继承公共ItemName属性。我分别有ItemAName和ItemBName属性…@AdolfoPerez但是你的例子说newitemb{ItemName=bb}我想到了这个,但是在我的例子中不起作用。项目A和项目B不继承公共ItemName属性。我分别有ItemAName和ItemBName属性…@AdolfoPerez,但是你的例子说新的ItemB{ItemName=bb}我对这个做了一点修改,但是我喜欢这个想法,谢谢你的帮助!:var result=Children.OfType.OrderBya=>a.ItemAName.ConcatChildren.OfType.OrderByb=>b.ItemBName.ToList;我对此做了一点修改,但我喜欢这个主意,谢谢你的帮助!:var result=Children.OfType.OrderBya=>a.ItemAName.ConcatChildren.OfType.OrderByb=>b.ItemBName.ToList;