Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I know that you asked for a LINQ solution, but LINQ seems complicated to use in this situation, especially if you want to adjust the <code>Sort</code> column as well. I suggest a plain old approach using for loops and indexes. It performs the sort operation in-place and does not created a new list.</p> <p>In order to make it reusable I create it as extension method for the <code>IList</code> interface, which makes it compatible to arrays too.</p> <p>In order to make it generic, you need some way to access the <code>Sort</code> column. Exposing this column through an interface would restrict the solution to classes implementing this interface. Therefore I opted for accessors that you have to pass as delegates. They also work if the <code>Sort</code> column has another name like <code>Order</code> for instance.</p> <pre><code>public static class ListExtensions { public static void MoveItem&lt;T&gt;(this IList&lt;T&gt; list, int fromIndex, int toIndex, Func&lt;T, int&gt; getSortKey, Action&lt;T, int&gt; setSortKey) { T temp = list[fromIndex]; int lastSortKey = getSortKey(temp); setSortKey(temp, getSortKey(list[toIndex])); if (fromIndex &gt; toIndex) { // Move towards beginning of list (upwards). for (int i = fromIndex; i &gt; toIndex; i--) { list[i] = list[i - 1]; int nextSortKey = getSortKey(list[i]); setSortKey(list[i], lastSortKey); lastSortKey = nextSortKey; } } else if (fromIndex &lt; toIndex) { // Move towards end of list (downwards). for (int i = fromIndex; i &lt; toIndex; i++) { list[i] = list[i + 1]; int nextSortKey = getSortKey(list[i]); setSortKey(list[i], lastSortKey); lastSortKey = nextSortKey; } } list[toIndex] = temp; } } </code></pre> <p>You can use the method like this</p> <pre><code>list.MoveItem(3, 1, x =&gt; x.Sort, (x, i) =&gt; x.Sort = i); </code></pre> <p>Note that you have to pass the list indexes and not the sort values.</p> <hr> <p>Here are the classes I used for the tests. Just set a breakpoint at the end of the two test methods in order to inspect the result in the locals window. Start the test in the Class View by right clicking on the <code>Test</code> class and choosing "Invoke Static Method".</p> <pre><code>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&lt;SomeItem&gt; list = InitializeList(); list.MoveItem(3, 1, x =&gt; x.Sort, (x, i) =&gt; x.Sort = i); } public static void MoveDown() { List&lt;SomeItem&gt; list = InitializeList(); list.MoveItem(1, 3, x =&gt; x.Sort, (x, i) =&gt; x.Sort = i); } private static List&lt;SomeItem&gt; InitializeList() { return new List&lt;SomeItem&gt; { 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" } }; } } </code></pre> <hr> <p><strong>UPDATE</strong></p> <p>A note on adjusting the sort key: The solution above works well if the sort keys are in-order and unique. If this is not always the case, a more robust solution would be to adjust the sort keys before storing the list back to the DB by simply setting the sort key equal to the list index. This would simplify the <code>MoveItem</code> method.</p> <pre><code>public static void MoveItem&lt;T&gt;(this IList&lt;T&gt; list, int fromIndex, int toIndex) { T temp = list[fromIndex]; if (fromIndex &gt; toIndex) { // Move towards beginning of list (upwards). for (int i = fromIndex; i &gt; toIndex; i--) { list[i] = list[i - 1]; } } else if (fromIndex &lt; toIndex) { // Move towards end of list (downwards). for (int i = fromIndex; i &lt; toIndex; i++) { list[i] = list[i + 1]; } } list[toIndex] = temp; } public static void FixSortKeys&lt;T&gt;(this IList&lt;T&gt; list, Action&lt;T, int&gt; setSortKey) { for (int i = 0; i &lt; list.Count; i++) { setSortKey(list[i], i); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload