So my little brother sent over the code below last week and asked me if there was a better way to do it. When I first read through it I was thinking…I can’t believe people still use the good ole to/from listbox style UI. I don’t remember the last time I had to write this code, but I’m pretty sure it was prior to LINQ.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protected void moveItems(ListControl sendingLB, ListControl receivingLB) | |
{ | |
ListBox temp = new ListBox(); | |
List<ListItem> tempList = new List<ListItem>(); | |
Comparison<ListItem> compare = new Comparison<ListItem>(CompareListItems); | |
foreach (ListItem li in sendingLB.Items) | |
if (li.Selected && receivingLB.Items.FindByText(li.Text) == null) | |
receivingLB.Items.Add(li); | |
else | |
temp.Items.Add(li); | |
foreach (ListItem li in receivingLB.Items) | |
tempList.Add(li); | |
tempList.Sort(compare); | |
receivingLB.Items.Clear(); | |
receivingLB.Items.AddRange(tempList.ToArray()); | |
sendingLB.Items.Clear(); | |
foreach (ListItem li in temp.Items) | |
sendingLB.Items.Add(li); | |
receivingLB.ClearSelection(); | |
} | |
int CompareListItems(ListItem li1, ListItem li2) | |
{ | |
return String.Compare(li1.Text, li2.Text); | |
} |
So here’s what I came up with in my response using LINQ.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protected void moveItems(ListControl source, ListControl destination) | |
{ | |
var getListItemsFrom = new Func<ListControl, List<ListItem>> | |
(x => x.Items.Cast<ListItem>().ToList()); | |
var selectedItems = getListItemsFrom(source).Where(x => x.Selected); | |
var nonSelectedItems = getListItemsFrom(source).Where(x => !x.Selected); | |
var currentDestinationItems = getListItemsFrom(destination); | |
//Thanks Ryan for the .Except instead of the .Where(not) | |
currentDestinationItems.AddRange(selectedItems.Except(currentDestinationItems)); | |
ReloadItemsFor(destination, /*with*/ currentDestinationItems); | |
ReloadItemsFor(source, /*with*/ nonSelectedItems); | |
destination.ClearSelection(); | |
} | |
private void ReloadItemsFor(ListControl listControl, IEnumerable<ListItem> itemsToAdd) | |
{ | |
listControl.Items.Clear(); | |
listControl.Items.AddRange(itemsToAdd.OrderBy(x => x.Text).ToArray()); | |
} |
Basically I was able to get rid of all the for loops, sorting, adding items, and most importantly, the new version is more readable.