如何让用户选择如何使用变量对其列表进行排序?

时间:2018-04-08 22:09:04

标签: c# linq sorting

用户输入的信息可以按升序和降序的多种方式排序,我试图让用户选择他想要查看数据的方式:

有没有办法设置用户输入的变量并对数据进行排序,而不是多次重复代码,具体取决于输入:

var empName = el.Select(i => new { i.ID, i.FullName });
    if(emsort.Text="text1")
    empName.OrderBy(i.text1);
else if...

做一些更短的事情,如:

 string sort=emsort.Text ;
empName.OrderBy(sort);

4 个答案:

答案 0 :(得分:2)

如果我理解你的问题,你想要使用存储在emsort.Text中的属性名称动态排序,那么你可以使用表达式:

假设empNameIEnumerable<Employee>,请使用此:

private static Func<Employee, dynamic> GetSortable(string sortablePoperty)
    {
        var param = Expression.Parameter(typeof(Employee), "e");
        var member = Expression.Property(param, sortablePoperty);
        Expression memberAsObject = Expression.Convert(member, typeof(object));
        return Expression.Lambda<Func<Employee, dynamic>>(memberAsObject, param).Compile();
    }

然后使用它:

string sort=emsort.Text ;
empName.OrderBy(GetSortable(sort));

如果empNameIQueryable<Employee>,请使用此:

private static Expression<Func<Employee, dynamic>> GetSortable(string sortablePoperty)
    {
        var param = Expression.Parameter(typeof(Employee), "e");
        var member = Expression.Property(param, sortablePoperty);
        Expression memberAsObject = Expression.Convert(member, typeof(object));
        return Expression.Lambda<Func<Employee, dynamic>>(memberAsObject, param);
    }

答案 1 :(得分:1)

如果你问题中的用户是某个调用你的函数的软件,那么用户就会知道el序列中对象的类型:他知道元素的属性在el序列中,他知道他希望如何订购。

为什么不让这个用户在OrderBy中使用keySelector

创建扩展功能:

static class QueryableExtensions
{
    IQueryable<MyType> SelectAndSort<TSource, TResult>(this IQueryable<TSource source,
        Expression<Func<TSource, TResult>> selector, 
        Expression<Func<TSource, TKey>> sortKeySelector,
        System.ComponentModel.ListSortDirection sortDirection)
    {
        var selectBeforeOrdering = myRepository.el.Select(selector);
        // note: this is still an IQueryable, only the query has been made,
        // the database is not accessed yet!

        IQueryable<TResult> result = (sortDirection == ListSortDirectrion.Ascending) ?
            // sort in ascending order:
            selectBeforeOrdering.OrderBy(sortKeySelector) :
            // else: selec in descending order:
            selectBeforeOrdering.OrderByDescending(sortKeySelector);

        return result;
    }
}

用法:假设您的用户知道您的el,并且他想要几个字段,按您el

的某个属性排序
using (var myDbContext = new DbContext(...))
{
    IQueryable myEls = myDbContext.el;

    var mySelectedItems = myEls.SelectAndSore(
        // selector: what properties do I as a user want?
        el => new
        {
             Id = el.Id,
             FullName = el.FullName,
             ... // other desired properties
        },
        // sortSelector: how do I want my selected items to be sorted?
        selectedItem => selectedItem.FullName,
        // direction:
        ListSortDirection.Descending);

        // note: until now the database has not been accessed
        // only the Expression of the query has been created.

        // depending on what you want as a result: ToList / ToArray / First / ...
        return mySelectedItems.ToList();
    }

另一方面,如果您的用户不是软件,而是操作员,他必须选择他希望订购项目的列,他必须有一种方法告诉计算机应该对哪个列进行排序。

通常通过单击列来完成。另一种方法可以是在组合框中选择一个值。无论如何,您必须将某些内容附加到列或包含sortKeySelector的组合框值:

class MySortableColumn<TDisplayedProperty> : DataGridViewColumn 
   // or whatever column class you are using
{
    public Expression<Func<MyDisplayedItem, TDisplayedProperty>> SortKeySelector{get;set;}
}

现在您有几个列,每个列都显示MyDisplayedItem的一个属性:

var columnId = new MySortableColumn<int>()
{
    SortKeySelector = displayedItem => myDisplayedItem.Id,
};
var columnFullName = new MyStortableColumn<string>()
{
    SortKeySelector = displayedItem => myDisplayedItem.Id,
}
// etc.

每当操作员点击一列时,都会提取sortKey并将其用作参数来对项目进行排序:

void SortColumn(SortableColumn column)
{
     var sortedItems = Sort(column.SortKeySelector, ListSortOrder...);
     Display(sortedItems);
}

答案 2 :(得分:1)

正如我所假设的,el已实现(即,例如,它不仅仅是数据库的入口点),因此您可以使用反射:

var sort = emsort.Text;
PropertyInfo property = null;
var sortedData = el.Select(i => new { i.ID, i.FullName })
     .OrderBy(x => 
     {
          property = property ?? x.GetType().GetProperty(sort);
          return property.GetValue(x);
     }).ToList();

答案 3 :(得分:0)

这是我必须写的代码的一部分:

if (emord.Text == "Ascending")
        {

            if (emsort.Text == "ID")
            {
                var empName = el.Select(i => new { i.ID, i.FullName }).OrderBy(x => x.ID);
                var empNamenAmp = el.Select(i => new { i.ID, i.FullName, i.Salary, i.Currency, i.Per }).OrderBy(x => x.ID);
                var empNamenAmpnwh = el.Select(i => new { i.ID, i.FullName, i.Salary, i.Currency, i.Per, i.Hours }).OrderBy(x => x.ID);
                var empNamenwh = el.Select(i => new { i.ID, i.FullName, i.Hours }).OrderBy(x => x.ID);
                var empNamenbd = el.Select(i => new { i.ID, i.FullName, i.Date }).OrderBy(x => x.ID);
                var empNamenad = el.Select(i => new { i.ID, i.FullName, i.Location }).OrderBy(x => x.ID);
                var empNamenpn = el.Select(i => new { i.ID, i.FullName, i.PhoneNb }).OrderBy(x => x.ID);
                var empNamena = el.Select(i => new { i.ID, i.FullName, i.Age }).OrderBy(x => x.ID);
                if (empfilcomb.Text == "Name")
                {
                    dispfil.Clear();
                    foreach (var x in empName)
                        dispfil.Text += x.ID + ", " + x.FullName + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Amount paid")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenAmp)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Salary + " " + x.Currency + " " + x.Per + Environment.NewLine;
                }

                else if (empfilcomb.Text == "Name and Work Hours")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenwh)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Hours + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name,Amount paid and Work Hours")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenAmpnwh)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Salary + " " + x.Currency + " " + x.Per + ", " + x.Hours + Environment.NewLine;

                }
                else if (empfilcomb.Text == "Name and Birthday")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenbd)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Date + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Address")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenad)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Location + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Phone Number")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenpn)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.PhoneNb + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Age")
                {
                    dispfil.Clear();
                    foreach (var x in empNamena)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Age + Environment.NewLine;

                }
            }
            else if (emsort.Text == "Name")
            {
                var empName = el.Select(i => new { i.ID, i.FullName }).OrderBy(x => x.FullName);
                var empNamenAmp = el.Select(i => new { i.ID, i.FullName, i.Salary, i.Currency, i.Per }).OrderBy(x => x.FullName);
                var empNamenAmpnwh = el.Select(i => new { i.ID, i.FullName, i.Salary, i.Currency, i.Per, i.Hours }).OrderBy(x => x.FullName);
                var empNamenwh = el.Select(i => new { i.ID, i.FullName, i.Hours }).OrderBy(x => x.FullName);
                var empNamenbd = el.Select(i => new { i.ID, i.FullName, i.Date }).OrderBy(x => x.FullName);
                var empNamenad = el.Select(i => new { i.ID, i.FullName, i.Location }).OrderBy(x => x.FullName);
                var empNamenpn = el.Select(i => new { i.ID, i.FullName, i.PhoneNb }).OrderBy(x => x.FullName);
                var empNamena = el.Select(i => new { i.ID, i.FullName, i.Age }).OrderBy(x => x.FullName);
                if (empfilcomb.Text == "Name")
                {
                    dispfil.Clear();
                    foreach (var x in empName)
                        dispfil.Text += x.ID + ", " + x.FullName + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Amount paid")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenAmp)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Salary + " " + x.Currency + " " + x.Per + Environment.NewLine;
                }

                else if (empfilcomb.Text == "Name and Work Hours")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenwh)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Hours + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name,Amount paid and Work Hours")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenAmpnwh)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Salary + " " + x.Currency + " " + x.Per + ", " + x.Hours + Environment.NewLine;

                }
                else if (empfilcomb.Text == "Name and Birthday")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenbd)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Date + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Address")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenad)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Location + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Phone Number")
                {
                    dispfil.Clear();
                    foreach (var x in empNamenpn)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.PhoneNb + Environment.NewLine;
                }
                else if (empfilcomb.Text == "Name and Age")
                {
                    dispfil.Clear();
                    foreach (var x in empNamena)
                        dispfil.Text += x.ID + ", " + x.FullName + ", " + x.Age + Environment.NewLine;

                }
            }

我问是否有一个更短的方法来实现它:我可以使用的是什么。似乎没有,但非常感谢帮助,我确定你们提供的内容是有用的。