Wilsonhut

Deal with it or don't

A Betterer ToSelectListItems

Last year, I did a post about Select List building in asp.net MVC. It’s now even better:

public static class DropDownExtensions
{
  public static DropDownViewModel<TValue> ToDropDownViewModel<T, TValue>(this IEnumerable<T> items,
                                                                          Func<T, string> textSelector,
                                                                          Func<T, TValue> valueSelector)
  {
    return ToDropDownViewModel(items, textSelector, valueSelector, item => null);
  }
  public static DropDownViewModel<TValue> ToDropDownViewModel<T, TValue>(this IEnumerable<T> items,
                                                                          Func<T, string> textSelector,
                                                                          Func<T, TValue> valueSelector,
                                                                          Func<T, IComparable> sortSelector)
  {
    return new DropDownViewModel<TValue>(items
                                          .Select(item =>
                                                   new DropDownItem<TValue>
                                                     {
                                                       Text = textSelector(item),
                                                       Value = valueSelector(item),
                                                       Sort = sortSelector(item)
                                                     }));
  }
}


Again, this could be a Tuple:

public class DropDownItem<TValue>
{
  public string Text { get; set; }
  public TValue Value { get; set; }
  public IComparable Sort { get; set; }
}


And the DropDownViewModel:

public class DropDownViewModel<TValue>
{
  private readonly IEnumerable<DropDownItem<TValue>> _dropDownItems;
  internal DropDownViewModel(IEnumerable<DropDownItem<TValue>> dropDownItems)
  {
    _dropDownItems = dropDownItems;
  }
  public IEnumerable<SelectListItem> GetSelectListItems(TValue selectedValue, bool addEmpty = false)
  {
    return GetSelectListItems(item => Equals(item.Value, selectedValue), addEmpty);
  }
  public IEnumerable<SelectListItem> GetSelectListItems(Func<DropDownItem<TValue>, bool> getIsSelected, bool addEmpty = false)
  {
    if (addEmpty)
    {
      yield return new SelectListItem();
    }
    foreach (var item in _dropDownItems.OrderBy(ddi => ddi.Sort))
    {
      yield return new SelectListItem
      {
        Text = item.Text,
        Value = item.Value.ToString(),
        Selected = getIsSelected(item),
      };
    }
  }
}
Advertisements

4 responses to “A Betterer ToSelectListItems

  1. Jean-François Beauchamp January 16, 2012 at 8:49 pm

    Could you please tell where you put this code in a typical ASP.Net project, and also give an example of how to use this?

  2. wilsonhut January 17, 2012 at 2:27 pm

    Sure.
    The DropDownExtensions can go anywhere, really. You’ll just have to add a ‘using …’ wherever you want to reference it in your code. The other classes can also go anywhere. They are all very ‘view’-related, so put them with the other view-related code.
    As far as examples, check out this post, and scroll halfway down: https://wilsonhut.wordpress.com/2010/09/14/a-better-toselectlistitems/

  3. Patrick Jackson October 8, 2012 at 3:16 pm

    If you wanted to add an item to the beginning of the list, how best would it be to do it?

    • wilsonhut October 8, 2012 at 5:18 pm

      If you want to add a BLANK entry to the beginning, just pass true as the second parameter of the GetSelectListItems method.
      If you want to add something specific, you could easily create an overload of GetSelectListItems that would “yeild return” your thing before “yield returning” the other items… or add a method to DropDownViewModel to allow adding DropDownItems (you’d have to make _dropDownItems an IList rather than an IEnumerable)

      OR… just before calling ToDropDownViewModel, get the items the way you want them:
      So instead of:
      viewModel.StateList = _repo.GetStates().ToDropDownViewModel(…);
      Use this:
      viewModel.StateList = (new []{new State(“East Oklahoma”, 51)}.Concat(_repo.GetStates())).ToDropDownViewModel(…);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: