1

私は次の簡略化されたクラスを持っています:

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コレクションを2つの条件に基づいて並べ替えようとしています。

  1. すべてのアイテムAはコレクションの最初に来る必要があります
  2. アイテムAはItemANameでソートする必要があります
  3. アイテムBはItemBNameでソートする必要があります

したがって、並べ替えた後、私は次のようなものを期待します:

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

しかし、名前はソートされていません...

ありがとう!

4

3 に答える 3

2
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);
}
于 2012-12-05T17:23:30.677 に答える
1

これにより、すべてのAが取得され、ANameで並べ替えられてから、B名で並べ替えられたすべてのBと連結されます。

var result = Children.OfType<ItemA>().OrderBy(a => a.ItemAName).Cast<Base>()
    .Concat(Children.OfType<ItemB>().OrderBy(b => b.ItemBName));

これが私が使用するデザインかどうかはわかりません...この種の並べ替えを容易にするために、基本クラスに何かを追加することを検討してください。

于 2012-12-05T17:30:50.400 に答える
1

を指定してアイテムを初期化しますItemNameが、そのようなプロパティを定義することも定義するBaseContainerこともありません。ItemAItemB

ItemName in the base classBaseContainer`を宣言します。アイテムクラスはこのプロパティを自動的に継承し、そこでそのようなフィールドを再定義する必要はありません。

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<BaseContainer>です。.ToList()結果をリストとして保存する場合は、を追加できます。

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

アップデート

あなたのコメントによると、あなたは共通のItemName財産を持っていません。なんで?あなたは本当にそれを持っているべきです。クラスをリファクタリングします。何らかの理由でinが不要な場合はItemNameBaseContainer抽象基本クラスを作成するかItem、アイテムに共通のインターフェイスを実装させます。

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

public class ItemA : Item
{
}

public class ItemB : Item
{
}

または

public interface IItem
{
    string ItemName { get; set; }
}

public class ItemA : BaseContainer, IItem
{
    public string ItemName { get; set; }
}

public class ItemB : BaseContainer, IItem
{
    public string ItemName { get; set; }
}

今、あなたはこのようにソートすることができます

var result = base.Children
    .OfType<Item> // or .OfType<IItem>
    .OrderBy(i => i.GetType().Name)
    .ThenBy(i => i.ItemName);

結果はIEnumerable<Item>またはになりIEnumerable<IItem>ます。


もう1つのオプションはToString、すべてのオブジェクトがから継承するメソッドをオーバーライドすることSyste.Objectです。

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

    public override string ToString()
    {
        return "ItemA: " + ItemAName;
    }
}

これにより、両方の条件(タイプによる並べ替えと名前による並べ替え)を1つのステップで実行できるため、並べ替えが簡単になります。この文字列は、リストボックス、コンボボックスなどにも表示されます。

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);
于 2012-12-05T17:31:11.530 に答える