views:

48

answers:

3

In ASP.NET MVC, is it possible to fill the list of values of a Html.DropDownList from multiple data sources along with multiple manually entered values?

Basically, I envision it being formated like the below using something along the lines of OPTGROUP:

**Group 1**  
Manual Item 1
Manual Item 2
**Group 2**
DS1 Item 1
DS1 Item 2
**Group 3**
DS2 Item 1
DS2 Item 2

I've thought about using a view on the DB and getting the data from that, however, I've not really the faintest how to lay it out like above using helpers and to pass the data to it from multiple sources.

Thanks for any help in advance.

A: 

It seems it would be easier for you to write your own helper. The basic syntax to do that is this:

// The class can be named anything, but must be static and accessible
public static class HtmlHelperExtensions 
{
    // The method name is what you want to call on Html, 
    // in this case Html.CoolSelectList(arguments...)
    // 
    // The method has to be static, and the first argument should be of the type
    // you're extending (in this case HtmlHelper, which is the type of the
    // Html property on your view). The first argument must be prefixed with the
    // "this" keyword, to indicate it's an extension method.
    // 
    // All the following arguments will be arguments that you supply when calling
    public static string CoolSelectList(this HtmlHelper helper, 
        IEnumerable<IEnumerable<CoolThingThatWeMakeAListOf>> groups)
    {
        // I chose an argument of type IEnumerable<IEnumerable<T>>, since that
        // allows you to create each group of item on its own (i.e. get them from
        // various data sources) and then add all of them to a list of groups
        // that you supply as argument. It is then easy to keep track of which 
        // items belong to which groups, etc.

        // Returned from the extension method is a string you have built, that
        // constitutes the html you want to output on your view. I usually use
        // the TagBuilder class to build the html.

        return "this is what will be on the page";
    }
}
Tomas Lycken
A: 

Many solutions exist for you problem. One would be the one that Tomas described, another is a Controller Action that returns PartialView, which contains the code to render the input and option tags, another solution would be to have the Controller Action populate the ViewData with a SelectList or have the SelectList as a strong type for your View/ViewUserControl (Partial).

mare
A: 

As always start with a model (actually start with a unit test but no time for this here):

public class MyModel
{
    public string SelectedItem { get; set; }
    public IEnumerable<SelectListItem> Items { get; set; }
}

Then a controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var items1 = new[] 
        {  
            new { Value = "1", Text = "Manual Item 1" },
            new { Value = "2", Text = "Manual Item 2" },
        };

        // TODO: Go fetch those from your repo1
        var items2 = new[] 
        {  
            new { Value = "3", Text = "DS1 Item 1" },
            new { Value = "4", Text = "DS1 Item 2" },
        };

        // TODO: Go fetch those from your repo2
        var items3 = new[] 
        {  
            new { Value = "5", Text = "DS2 Item 1" },
            new { Value = "6", Text = "DS2 Item 2" },
        };

        var items = items1.Concat(items2).Concat(items3);
        var model = new MyModel
        {
            Items = new SelectList(items, "Value", "Text")
        };
        return View(model);
    }
}

And finally a strongly typed view to the model:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyApp.Models.MyModel>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <%= Html.DropDownListFor(x => x.SelectedItem, Model.Items) %>
</asp:Content>

You will probably define an intermediary type to avoid the anonymous types that I've used for brevity.

Remark: If your original question was about using an OPTGROUP then ignore my answer and make your intention clear so that you can get a more adapted answer.

Darin Dimitrov