The issue with select \ list boxes is that when the form is submitted only the selected items are submitted with the form, so if you have 20 items in the select box, select 3 of them and submit the form then your controller code has no idea how many items were in your list box originally, only that the user has selected three of them.
So you need to track the non-selected items yourself. There are loads of different ways of doing this, but in the sample code below I simply store them in a hidden field as a comma separated list.
The updated model
public class NumberClass
{
public string currentLeftNumbers { get; set; }
public IEnumerable<SelectListItem> leftnumbers { get; set; }
public IEnumerable<int> leftSelectednumbers { get; set; }
public string currentRightNumbers { get; set; }
public IEnumerable<SelectListItem> rightnumbers { get; set; }
public IEnumerable<int> rightSelectednumbers { get; set; }
}
View
@using (Html.BeginForm())
{
<input type="hidden" name="CurrentLeftNumbers" value="@Model.currentLeftNumbers"/>
<div class="col-md-6" style="font-family:Arial">
@Html.ListBoxFor(m => m.leftSelectednumbers, Model.leftnumbers, new { size = 20, @class = "listBox" })
<br />
<input type="submit" value="move right" />
</div>
<input type="hidden" name="CurrentRightNumbers" value="@Model.currentRightNumbers" />
<div class="col-md-6" style="font-family:Arial">
@Html.ListBoxFor(m => m.rightSelectednumbers, Model.rightnumbers, new { size = 20, @class = "listBox" })
<br />
<input type="submit" value="move left" />
</div>
}
Controller
[HttpGet]
public ActionResult Index()
{
List<int> items = new List<int>();
for (int i = 1; i <= 20; i++)
{
items.Add(i);
}
NumberClass num = GetModel(items, new List<int>());
return View(num);
}
[HttpPost]
public ActionResult Index(NumberClass model)
{
List<int> left = GetNumbers(model.currentLeftNumbers);
List<int> right = GetNumbers(model.currentRightNumbers);
if (model.leftSelectednumbers != null)
{
foreach (var i in model.leftSelectednumbers)
{
left.Remove(i);
right.Add(i);
}
}
if (model.rightSelectednumbers != null)
{
foreach (var i in model.rightSelectednumbers)
{
right.Remove(i);
left.Add(i);
}
}
return View(GetModel(left, right));
}
private List<int> GetNumbers(string numbers)
{
if (string.IsNullOrWhiteSpace(numbers))
{
return new List<int>();
}
else
{
return numbers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(n => int.Parse(n)).ToList();
}
}
private NumberClass GetModel(IEnumerable<int> left, IEnumerable<int> right)
{
NumberClass model = new NumberClass();
if (left.Any())
{
model.currentLeftNumbers = left.Select(n => n.ToString()).Aggregate((x, y) => x + "," + y);
model.leftnumbers = left.OrderBy(x => x).Select(n => new SelectListItem { Value = n.ToString(), Text = n.ToString() });
}
else
{
model.leftnumbers = new List<SelectListItem>();
}
if (right.Any())
{
model.currentRightNumbers = right.Select(n => n.ToString()).Aggregate((x, y) => x + "," + y);
model.rightnumbers = right.OrderBy(x => x).Select(n => new SelectListItem { Value = n.ToString(), Text = n.ToString() });
}
else
{
model.rightnumbers= new List<SelectListItem>();
}
return model;
}
You'll probably need to step through the code to see how it is working.