Пользовательский вид DataTable, где нужен индекс - PullRequest
1 голос
/ 12 июня 2019

Как видно из заголовка, мне нужна пользовательская сортировка для моего DataTable, где я использую индекс DataRow, и результатом должен быть EnumerableRowCollection или OrderedEnumerableRowCollection, потому что я хочу таблицу (порядок по умолчанию) и DataView (настраиваемый порядок).

Порядок, который я хочу: сначала отсортировать по нескольким столбцам (например, имя, фамилия, ...). Затем разделите таблицу на table1 и table2 (только половина таблицы). Затем поочередно выбирайте из первой и второй таблицы. Результат должен быть

строка таблицы1
строка таблицы2
строка таблицы1

исходная таблица не должна быть затронута, и результат должен быть ссылкой на исходную таблицу.

internal static DataView GetSortedView(this DataTable table)
{
    return table.GetSortedTable().AsDataView();
}

internal static void OrderedEnumerableRowCollection<DataRow> GetSortedTable(this DataTable table)
{

int half = table.Rows.Count / 2;
//sort columns by name for example
var enumerable = table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());

//here is the tricky part
enumerable= enumerable.OrderBy(row =>
                    {
                        int myIndex = ?; //I cannot use table.Rows.IndexOf(row) because the order of the current OrderedEnumerableRowCollection should be used and not the default order of the table

                        bool upperHalf = myIndex > half;
                        if (upperHalf)
                        {
                            myIndex -= half;
                        }

                        return new CustomSortItem(myIndex , upperHalf);
                    }, new CustomSort());
return enumerable;
}

Сначала я попытался добавить новый столбец для индексов, но на самом деле это не работает, потому что, когда я пытаюсь удалить столбец, в конце я получаю исключение из-за отложенной загрузки.

internal static void OrderedEnumerableRowCollection<DataRow> GetSortedTable(this DataTable table)
{

//create another column for an index
string tempSortName = "[TEMP_SORT]";
table.Columns.Add(tempSortName);

//sort columns by Name for example
var enumerable= table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());

//set the temporary order (index)
int count = 0;
foreach(DataRow row in enumerable)
{
    row[tempSortName] = count++;
}

//here is the tricky part
int half = table.Rows.Count / 2;
enumerable= enumerable.OrderBy(row =>
                    {
                        int myIndex = int.parse(row[tempSortName].ToString()); //exception here. column not found

                        bool upperHalf = myIndex  > half;
                        if (upperHalf)
                        {
                            myIndex  -= half;
                        }

                        return new CustomSortItem(myIndex , upperHalf);
                    }, new CustomSort());

                    table.Columns.Remove(tempSortName);
return enumerable;
}

Я также не хочу использовать IEnumerable, потому что когда я создаю DataView, мне нужно создать другую таблицу, чтобы создать ее, а затем ссылка теряется (view.Table - это не оригинальная таблица, а просто копия без ссылки).

IEnumerable<DataRow> enumerable...
enumerable.CopyToDataTable().AsDataView();
// I have to call CopyToDataTable() in order to create a DataView

Ответы [ 2 ]

0 голосов
/ 14 июня 2019

Через некоторое время я нашел решение, и решение отличается для GetSortedTable и GetSortedView (у каждого есть свое решение).Буду признателен, если у кого-то есть лучшее решение.

internal static void DataView GetSortedView(this DataTable table)
{

   //create another column for an index
   string tempSortName = "[TEMP_SORT]";
   table.Columns.Add(tempSortName);

   //sort columns by Name for example
   var enumerable= table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());

   //set the temporary order (index)
   int count = 0;
   foreach(DataRow row in enumerable)
   {
       row[tempSortName] = count++;
   }

   //here is the tricky part
   int half = table.Rows.Count / 2;
   enumerable= enumerable.OrderBy(row =>
    {

      if (int.TryParse(row[tempSortName]?.ToString(), out int myIndex )) //everything here is triggered if row[tempSortName] is set... or before it is set... idk... wtf. so there is a new column but there are not any indices in it (or just one)
       {
         myIndex++;
         bool upperHalf = myIndex  > half;
         if (upperHalf)
         {
            myIndex  -= half;
         }
         return new CustomSortItem(myIndex , upperHalf);
       }
    }, new CustomSort());

   DataView view = enumerable.AsDataView();
   view.Table.Columns.Remove(tempSortName);

   return view;
}


internal static IEnumerable<DataRow> GetSortedTable(this DataTable table)
{
   IEnumerable<DataRow> result;
   //sort columns by Name for example
   var enumerable= table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());
   int half =  table.Rows.Count / 2;
   IEnumerable<DataRow> one = enumerable.Take(half);
   IEnumerable<DataRow> two = enumerable.Skip(half);
   result = one.InterleaveEnumerationsOfEqualLength(two);
   return result;
 }

internal static IEnumerable<DataRow> InterleaveEnumerationsOfEqualLength<DataRow>(this IEnumerable<DataRow> first, IEnumerable<DataRow> second)
{
   using (IEnumerator<DataRow> enumerator1 = first.GetEnumerator(), enumerator2 = second.GetEnumerator())
   {
      while (enumerator1.MoveNext() && enumerator2.MoveNext())
      {
         yield return enumerator1.Current;
         yield return enumerator2.Current;
      }
    }
}
0 голосов
/ 14 июня 2019

Что если вы используете двухпараметрическую версию Select для подсчета строк по порядку?

enumerable = enumerable.Select((r, i) => new { r, i })
                       .OrderBy(ri => {
                            var upperHalf = ri.i > half;
                            var myIndex = ri.i - (upperHalf ? half : 0);
                            return new CustomSortItem(myIndex, upperHalf);
                        }, new CustomSort());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...