我在Winforms应用程序中有一个DataGridView。我想在其中选择一组行,并按列(Timestamp)...
对这些行进行排序其余行应保持原来的状态。 可以使用DGV的sort属性
来完成由于
答案 0 :(得分:3)
可以使用排序完成此操作 DGV的财产
否强>
DataGridView
上的Sort
method用于更简单的排序。例如Ascending或Descending排序,SortOrder
属性也只是用于“简单”排序。
可以实施此行为吗?肯定。
我认为最简单的方法就是:
DataGridView
但是,如果选择彼此不跟随的项目,则需要考虑如何处理,例如,如果选择索引{ 1, 3, 6, 9 }
,您可能希望将其附加到索引{{1} }。
修改强>
好的,所以我玩了一下这个,并提出了一种方法,你可以实现这一点。它不是很优化,但你会明白我的意思。
首先,这是我使用的1
- 方法:
SortSelectedIndices
然后我称之为:
static IEnumerable<T> SortSelectedIndices<T>(
IEnumerable<T> values,
IEnumerable<int> selectedIndices,
Func<IEnumerable<T>, IEnumerable<T>> sort)
{
var selectedValues = new List<T>();
for (var i = 0; i < selectedIndices.Count(); i++)
selectedValues.Add(values.ElementAt(selectedIndices.ElementAt(i)));
var sortedList = sort(selectedValues);
var finalList = new List<T>();
var startPositionFound = false;
for(var i = 0; i < values.Count(); i++)
{
if (selectedIndices.Contains(i))
{
if (startPositionFound) continue;
startPositionFound = true;
finalList.AddRange(sortedList);
}
else
finalList.Add(values.ElementAt(i));
}
return finalList;
}
这打印出以下内容:
static void Main(string[] args)
{
var unsorted = new[] {3, 5, 6, 1, 2, 87, 432, 23, 46, 98, 44};
var selected = new[] {1, 4, 7};
Print(unsorted);
var sort = new Func<IEnumerable<int>, IEnumerable<int>>(
(x) => x.OrderBy(y => y).ToList());
var sorted = SortSelectedIndices(unsorted, selected, sort);
Print(sorted);
}
我只是在这里使用一种简单的方法将其打印到控制台:
{ 3,5,6,1,2,87,432,23,46,98,44 }
{ 3,2,5,23,6,1,87,432,46,98,44 }
所以你可以做的就是有一个“排序”按钮,当你按下它时调用static void Print<T>(IEnumerable<T> values)
{
Console.Write("{ ");
Console.Write(string.Join(",", values));
Console.WriteLine(" }");
}
然后在你完成时重新绑定列表。 请记住我没有对此代码进行分析或重构,它可能没有您想要的那么快,我只想告诉您如何实现该解决方案。
答案 1 :(得分:1)
基于Filips对问题的定义,以及他作为正确答案的例子,我的一般性(没有泛型,没有Func)解决方案就是这样:
Public Function SortSelectedIndices(unsortedList As IEnumerable(Of Integer), selectedIndices As IEnumerable(Of Integer)) As IEnumerable(Of Integer)
If Not selectedIndices.Any() Then
Return unsortedList
End If
Dim extractedValues = From s In selectedIndices Select unsortedList(s)
Dim sortedExtractedValues = From e In extractedValues Order By e
Dim listWithoutExtractedValues = unsortedList.Except(extractedValues)
Dim resultList = New List(Of Integer)(listWithoutExtractedValues)
Dim firstSelectedIndex = Aggregate s In selectedIndices Order By s Into First()
resultList.InsertRange(firstSelectedIndex, sortedExtractedValues)
Return resultList
End Function
编辑:Filip刚刚指出问题标记为“C#”。但是在文中没有提到这一点,所以我认为它并不重要。我还假设任何熟悉.NET的读者都可以将“昏暗”翻译成“var”和喜欢的东西。 :-P
答案 2 :(得分:0)
当然,DataGridView无法做到这一点。因此,最好的解决方案是创建一个新的集合(List),用GridView中的选定行填充它,最后使用它的Sort方法来排序这些行。要按特定列对数据进行排序,您可以编写自定义IComparer类并将其传递给Sort方法或使用Linq:
var orderedList = someList.OrderBy(obj =&gt; obj.TimeStampField);
答案 3 :(得分:0)
您可以直接在DataGridView中进行任何可能的排序,方法是创建一个自定义IComparer,并将其传递给DataGridView.Sort(IComparer)。诀窍是弄清楚如何为IComparer提供所需的信息。
有关详细信息,请参见How to: Customize Sorting in the Windows Forms DataGridView Control / Custom Sorting Using the IComparer Interface,尤其是class RowComparer : System.Collections.IComparer
。
在您的情况下,我们必须
a)将每一行与其原始行号相关联,并且
b)指出是否有行参与排序。
对于特定问题,我们希望所有选定的行都保留在它们之前的任何行之后,以及它们之后的任何行之前。例如,如果要对0-9行进行排序,而对3-7行进行排序,则0-2行将保持其原始顺序,而8-9行也是如此。与要排序的所有行相同的行号,特别是第一行的行号。 (3)。然后,当两行具有相同的初始行号时,请按照您的排序标准进行排序。
向每行添加此“额外”信息的一种方法是向每行添加“隐藏”列。
第二种方法是将信息放入字典中,并将其传递给自定义IComparer类。
(未经测试的)代码采用这种方式:
void SomeMethod()
{
DataGridView dgv = ...;
// Iterate through the rows, building the dictionary.
Dictionary<DataGridViewRow, int> rowToRowNumber = ...;
int iFirstSelected = -1;
for (int iRow = 0; iRow < dgv.Rows.Count; iRow++)
{
DataGridViewRow row = dgv.Rows[iRow];
int iAdjusted = iRow;
if (row.Selected)
{
if (iFirstSelected < 0)
iFirstSelected = iRow;
iAdjusted = iFirstSelected;
}
rowToRowNumber[row] = iAdjusted;
}
// Sort.
dgv.Sort(new RowComparer(rowToRowNumber));
}
private class RowComparer : System.Collections.IComparer
{
// Values are the row numbers before the sort was done,
// with all rows to sort set to the same value (the row number of the first row to sort).
Dictionary<DataGridViewRow, int> _rowToRowNumber;
public RowComparer(Dictionary<DataGridViewRow, int> rowToRowNumber)
{
_rowToRowNumber = rowToRowNumber;
}
public int Compare(object x, object y)
{
DataGridViewRow row1 = (DataGridViewRow)x;
DataGridViewRow row2 = (DataGridViewRow)y;
// Keep rows in order.
int result = _rowToRowNumber(row1).CompareTo(_rowToRowNumber(row2));
if (result != 0)
return result;
// Same row number, these are the rows to sort.
return CustomCompare(row1, row2);
}
private int CustomCompare(DataGridViewRow row1, DataGridViewRow row2)
{
// Replace with your custom logic.
// TODO: If cells contain strings, may have to parse them into the
// original data types, and compare those typed values rather than the cell values themselves.
return row1.Cells[1].Value.CompareTo(row2.Cells[1].Value);
}
}
注意:如果创建行的对象位于row.Tag
中,则最好检索这些类型的对象,并对其属性进行比较:
private int CustomCompare(DataGridViewRow row1, DataGridViewRow row2)
{
MyClass ob1 = (MyClass)(row1.Tag);
MyClass ob2 = (MyClass)(row2.Tag);
return ob1.MyProp.CompareTo(ob2.MyProp);
}
答案 4 :(得分:0)
没有太多时间来解释,但这是我曾经做过的事情。
afterEach