8

このシナリオを検討してください:

約 50 のフィールドを持つクラスのリストがあります。ユーザーがどのフィールド リストを並べ替えるかに従って選択できるコンボボックスが必要です。たとえば、ユーザーが "F1" に従ってリストを並べ替える "F1" を選択した場合。

すべてのフィールドでソートしたくありませんif-else。次のトピックが表示されます。

オブジェクトのコレクションまたはリストをデータバインドするときのグリッドビューの並べ替え

しかし、私はその答えを使用できません。Expression Treeこの目的のためにどのように使用できますか?

ありがとう

編集1)

親愛なる@Thom Smithの回答によると、私はこのコードを書きました:

 using (NorthwindModel1.NorthwindEntities2 ent = new NorthwindModel1.NorthwindEntities2())
    {
        var query = from o in ent.Orders
                    where o.OrderID < 10257
                    select o;

        query.OrderBy("CustomerID", SortDirection.Ascending);

        GridView1.DataSource = query;
        GridView1.DataBind();
    }

しかし、それはソートされていませんでした。この方法でそのコードを書いた場合:

GridView1.DataSource = query.OrderBy(o=>o.CustomerID);

それはソートされています。問題はどこだ?

4

4 に答える 4

8

これに私が使用する方法は次のとおりです。

private IQueryable<T> OrderQuery<T>(IQueryable<T> query, OrderParameter orderBy)
{
    string orderMethodName = orderBy.Direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending";
    Type t = typeof(T);

    var param = Expression.Parameter(t, "shipment");
    var property = t.GetProperty(orderBy.Attribute);

    /* We can't just call OrderBy[Descending] with an Expression
     * parameter because the second type argument to OrderBy is not
     * known at compile-time.
     */
    return query.Provider.CreateQuery<T>(
        Expression.Call(
            typeof(Queryable),
            orderMethodName,
            new Type[] { t, property.PropertyType },
            query.Expression,
            Expression.Quote(
                Expression.Lambda(
                    Expression.Property(param, property),
                    param))
        ));
}

OrderParameter属性と方向を持つ単なる構造体です。

編集:追加の説明。

このメソッドは、オブジェクトDynamicOrderListのリストである私のクラスからのOrderParameterものです。1 つのフィールドでソートするだけでよい場合は、少し単純化できます。

private IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string attribute, SortDirection direction)
{
    try
    {
        string orderMethodName = direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending";
        Type t = typeof(T);

        var param = Expression.Parameter(t);
        var property = t.GetProperty(attribute);

        return query.Provider.CreateQuery<T>(
            Expression.Call(
                typeof(Queryable),
                orderMethodName,
                new Type[] { t, property.PropertyType },
                query.Expression,
                Expression.Quote(
                    Expression.Lambda(
                        Expression.Property(param, property),
                        param))
            ));
    }
    catch (Exception) // Probably invalid input, you can catch specifics if you want
    {
        return query; // Return unsorted query
    }
}

次に、次のように使用します。

myQuery = myQuery.OrderByDynamic("name", SortDirection.Ascending);

編集2:

public IQueryable<T> OrderBy<T>(this IQueryable<T> query, string attribute, SortDirection direction)
{
    return ApplyOrdering(query, attribute, direction, "OrderBy");
}

public IQueryable<T> ThenBy<T>(this IQueryable<T> query, string attribute, SortDirection direction)
{
    return ApplyOrdering(query, attribute, direction, "ThenBy");
}

private IQueryable<T> ApplyOrdering<T>(IQueryable<T> query, string attribute, SortDirection direction, string orderMethodName)
{
    try
    {
        if (direction == SortDirection.Descending) orderMethodName += "Descending";

        Type t = typeof(T);

        var param = Expression.Parameter(t);
        var property = t.GetProperty(attribute);

        return query.Provider.CreateQuery<T>(
            Expression.Call(
                typeof(Queryable),
                orderMethodName,
                new Type[] { t, property.PropertyType },
                query.Expression,
                Expression.Quote(
                    Expression.Lambda(
                        Expression.Property(param, property),
                        param))
            ));
    }
    catch (Exception) // Probably invalid input, you can catch specifics if you want
    {
        return query; // Return unsorted query
    }
}

と:

myQuery=myQuery.OrderBy("name", SortDirection.Ascending).ThenBy("date", SortDirection.Descending);
于 2012-09-19T13:39:50.413 に答える
5

OrderBy はインプレース ソートを行いません。評価時にソートされるシーケンスを返します。これは通常、怠惰に行われます。つまり、列挙されるまで何もしませ。現在のコードは、この非常に重要な戻り値を単純に破棄しています。修正は簡単です: 戻り値をキャッチします:

query = query.OrderBy("CustomerID", SortDirection.Ascending);

注: 同様に、"Where" を適用しても、既存のデータはフィルター処理されません。列挙されたときにフィルター処理されるシーケンスが返されます。したがって、フィルタリングしている場合は、次のようになります。

query = query.Where(...);
于 2012-09-22T16:17:35.237 に答える
-1

それが役立つことを願っています。C#リストを動的にフィルタリングするのに役立ちました

string jtSorting = "ContactName";
DashboardModel Sup = new DashboardModel();
List<Applicant> lstSup = Sup.GetonBoard();
lstSup = lstSup.AsQueryable().SortBy(jtSorting).ToList();
于 2014-10-22T11:53:50.947 に答える