Nilmag Nilmag - 3 months ago 11
ASP.NET (C#) Question

How to delete an item from this listbox?

I have a listbox where i need to be able to remove individual RegimeItems. These RegimItems belong to a specific user, but as they are right now the listbox shows them for specific user, so i don't know if i need to state that in the code. Currently it is showing no error however it does not return the listbox with the remaining RegimeItems, nor does it actually update the database with the changes.

Update: i am getting a null reference exception at

model.RequestedSelected
on the line
foreach (int selected in model.RequestedSelected)
in RemoveExercises.

Controller

[HttpGet]
public ActionResult ExerciseIndex(int? id, UserExerciseViewModel vmodel)
{
User user = db.Users.Find(id);
UserExerciseViewModel model = new UserExerciseViewModel { AvailableExercises = GetAllExercises(), RequestedExercises = ChosenExercises(user, vmodel) };
user.RegimeItems = model.RequestedExercises;
return View(model);
}
[HttpPost]
public ActionResult ExerciseIndex(UserExerciseViewModel model, string add, string remove, string send, int id, RegimeItem regimeItem)
{
User user = db.Users.Find(id);
user.RegimeItems = model.RequestedExercises;
RestoreSavedState(model);
if (!string.IsNullOrEmpty(add))
AddExercises(model, id);
else if (!string.IsNullOrEmpty(remove))
RemoveExercises(model, id);
SaveState(model);
return View(model);
}

void SaveState(UserExerciseViewModel model)
{
model.SavedRequested = string.Join(",", model.RequestedExercises.Select(p => p.RegimeItemID.ToString()).ToArray());
model.AvailableExercises = GetAllExercises().ToList();
}

void RemoveExercises(UserExerciseViewModel model, int id)
{
foreach (int selected in model.RequestedSelected)
{
RegimeItem item = model.RequestedExercises.FirstOrDefault(i => i.RegimeItemID == selected);
if (item != null)
{
User user = db.Users.Find(id);
user.RegimeItems.Remove(item);
}
RedirectToAction("ExerciseIndex");
}

void RestoreSavedState(UserExerciseViewModel model)
{
model.RequestedExercises = new List<RegimeItem>();

//get the previously stored items
if (!string.IsNullOrEmpty(model.SavedRequested))
{
string[] exIds = model.SavedRequested.Split(',');
var exercises = GetAllExercises().Where(p => exIds.Contains(p.ExerciseID.ToString()));
model.AvailableExercises.AddRange(exercises);
}
}

private List<Exercise> GetAllExercises()
{
return db.Exercises.ToList();
}

private List<RegimeItem> ChosenExercises(User user, UserExerciseViewModel model)
{
return db.Users
.Where(u => u.UserID == user.UserID)
.SelectMany(u => u.RegimeItems)
.ToList();
}


Models

public class User
{
public int UserID { get; set; }
public ICollection<RegimeItem> RegimeItems { get; set; }
public User()
{
this.RegimeItems = new List<RegimeItem>();
}
}
public class RegimeItem
{
public int RegimeItemID { get; set; }
public Exercise RegimeExercise { get; set; }
}


ViewModel

public class UserExerciseViewModel
{
public List<Exercise> AvailableExercises { get; set; }
public List<RegimeItem> RequestedExercises { get; set; }
public int? SelectedExercise { get; set; }
public int[] AvailableSelected { get; set; }
public int[] RequestedSelected { get; set; }
public string SavedRequested { get; set; }
}


View(Segment only)

<input type="submit" name="remove"
id="remove" value="<<" />
</td>
<td valign="top">
@Html.ListBoxFor(model => model.RequestedExercises, new MultiSelectList(Model.RequestedExercises, "RegimeItemID", "RegimeExercise.Name", Model.RequestedSelected))
</td>

Answer

Your model.RequestedExercises list doesn't have a RegimeItemID property. It's a list of items. I suspect what you actually want is more like:

foreach(int selected in RequestedSelected)
{
   RegimeItem item = model.RequestedExercises.FirstOrDefault(i => i.RegimeItemID == selected);
   if(item != null)
   {
      User user = db.Users.Find(id);
      user.RegimeItems.Remove(item);
   }
}

Hopefully, this gets you on the right track.

Comments