我知道你問過一個LINQ解決方案,但是在這種情況下LINQ看起來很複雜,特別是如果你想調整Sort
列。我建議使用循環和索引的普通舊方法。它在原地執行排序操作並且不創建新列表。
爲了使它可重用,我將它創建爲IList
接口的擴展方法,這也使得它與陣列兼容。
爲了使其具有通用性,您需要某種方式來訪問Sort
列。通過接口公開此列將限制解決方案實現此接口的類。因此,我選擇了必須作爲代表傳遞的訪問器。如果Sort
列有另一個名稱,例如Order
,它們也可以工作。
public static class ListExtensions
{
public static void MoveItem<T>(this IList<T> list, int fromIndex, int toIndex,
Func<T, int> getSortKey, Action<T, int> setSortKey)
{
T temp = list[fromIndex];
int lastSortKey = getSortKey(temp);
setSortKey(temp, getSortKey(list[toIndex]));
if (fromIndex > toIndex) { // Move towards beginning of list (upwards).
for (int i = fromIndex; i > toIndex; i--) {
list[i] = list[i - 1];
int nextSortKey = getSortKey(list[i]);
setSortKey(list[i], lastSortKey);
lastSortKey = nextSortKey;
}
} else if (fromIndex < toIndex) { // Move towards end of list (downwards).
for (int i = fromIndex; i < toIndex; i++) {
list[i] = list[i + 1];
int nextSortKey = getSortKey(list[i]);
setSortKey(list[i], lastSortKey);
lastSortKey = nextSortKey;
}
}
list[toIndex] = temp;
}
}
您可以使用該方法這樣
list.MoveItem(3, 1, x => x.Sort, (x, i) => x.Sort = i);
請注意,您必須通過列表索引和沒有排序值。
這裏是我用於測試的類。只需在兩種測試方法的最後設置一個斷點,以便檢查本地窗口中的結果。通過右鍵單擊Test
類並選擇「調用靜態方法」,在類視圖中開始測試。
public class SomeItem
{
public int Sort { get; set; }
public string Value { get; set; }
public override string ToString()
{
return String.Format("Sort = {0}, Value = {1}", Sort, Value);
}
}
public static class Test
{
public static void MoveUp()
{
List<SomeItem> list = InitializeList();
list.MoveItem(3, 1, x => x.Sort, (x, i) => x.Sort = i);
}
public static void MoveDown()
{
List<SomeItem> list = InitializeList();
list.MoveItem(1, 3, x => x.Sort, (x, i) => x.Sort = i);
}
private static List<SomeItem> InitializeList()
{
return new List<SomeItem> {
new SomeItem{ Sort = 1, Value = "foo1" },
new SomeItem{ Sort = 2, Value = "foo2" },
new SomeItem{ Sort = 3, Value = "foo3" },
new SomeItem{ Sort = 4, Value = "foo4" },
new SomeItem{ Sort = 5, Value = "foo5" }
};
}
}
UPDATE
關於調整排序關鍵字的注意事項:上述解決方案的工作很好,如果排序鍵是有序的和獨特的。如果情況並非總是如此,則通過簡單地將排序鍵設置爲等於列表索引,更強健的解決方案將是在將列表存儲回DB之前調整排序鍵。這將簡化MoveItem
方法。
public static void MoveItem<T>(this IList<T> list, int fromIndex, int toIndex)
{
T temp = list[fromIndex];
if (fromIndex > toIndex) { // Move towards beginning of list (upwards).
for (int i = fromIndex; i > toIndex; i--) {
list[i] = list[i - 1];
}
} else if (fromIndex < toIndex) { // Move towards end of list (downwards).
for (int i = fromIndex; i < toIndex; i++) {
list[i] = list[i + 1];
}
}
list[toIndex] = temp;
}
public static void FixSortKeys<T>(this IList<T> list, Action<T, int> setSortKey)
{
for (int i = 0; i < list.Count; i++) {
setSortKey(list[i], i);
}
}
你可以發佈進入列表中的對象的代碼嗎? –
你的意思是這個代碼? – Yustme
請在下次標記你指的是哪一種linq。 –