This project is read-only.

Request for New Feature

Coordinator
Feb 6, 2011 at 4:34 PM

Please post here requests for new features that you would like to be implemented in the Mvc Controls Toolkit

Feb 27, 2011 at 2:36 PM
Edited Feb 27, 2011 at 5:50 PM

Hi

if possible i would like a the DropDownListFor to have support for optgroup

ex:

 

<select>
  <optgroup label="Swedish Cars">
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
  </optgroup>
  <optgroup label="German Cars">
    <option value="mercedes">Mercedes</option>
    <option value="audi">Audi</option>
  </optgroup>
</select>

maybe a new helper named Html.DropDownGroupListFor

example taken from http://stackoverflow.com/questions/607188/support-for-optgroup-in-dropdownlist-net-mvc

 

using System;using System.Collections;using System.Collections.Generic;using System.Globalization; using System.Linq;using System.Linq.Expressions;using System.Text; using System.Web;using System.Web.Mvc;using System.Web.Routing;

public class GroupedSelectListItem : SelectListItem
{
    public string GroupKey { get; set; }
    public string GroupName { get; set; }
}

public static partial class HtmlHelpers
{

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name)
    {
        return DropDownListHelper(htmlHelper, name, null, null, null);
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList)
    {
        return DropDownListHelper(htmlHelper, name, selectList, null, null);
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, string optionLabel)
    {
        return DropDownListHelper(htmlHelper, name, null, optionLabel, null);
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, null, htmlAttributes);
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, null, new RouteValueDictionary(htmlAttributes));
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel)
    {
        return DropDownListHelper(htmlHelper, name, selectList, optionLabel, null);
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, optionLabel, htmlAttributes);
    }

    public static MvcHtmlString DropDownGropList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, optionLabel, new RouteValueDictionary(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, null /* htmlAttributes */);
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, new RouteValueDictionary(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, htmlAttributes);
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, null /* htmlAttributes */);
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, new RouteValueDictionary(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes);
    }

    private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
    {
        return SelectInternal(htmlHelper, optionLabel, expression, selectList, false /* allowMultiple */, htmlAttributes);
    }


    // Helper methods

    private static IEnumerable<GroupedSelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)
    {
        object o = null;
        if (htmlHelper.ViewData != null)
        {
            o = htmlHelper.ViewData.Eval(name);
        }
        if (o == null)
        {
            throw new InvalidOperationException(
                String.Format(
                    CultureInfo.CurrentCulture,
                    "Missing Select Data",
                    name,
                    "IEnumerable<GroupedSelectListItem>"));
        }
        IEnumerable<GroupedSelectListItem> selectList = o as IEnumerable<GroupedSelectListItem>;
        if (selectList == null)
        {
            throw new InvalidOperationException(
                String.Format(
                    CultureInfo.CurrentCulture,
                    "Wrong Select DataType",
                    name,
                    o.GetType().FullName,
                    "IEnumerable<GroupedSelectListItem>"));
        }
        return selectList;
    }

    internal static string ListItemToOption(GroupedSelectListItem item)
    {
        TagBuilder builder = new TagBuilder("option")
        {
            InnerHtml = HttpUtility.HtmlEncode(item.Text)
        };
        if (item.Value != null)
        {
            builder.Attributes["value"] = item.Value;
        }
        if (item.Selected)
        {
            builder.Attributes["selected"] = "selected";
        }
        return builder.ToString(TagRenderMode.Normal);
    }

    private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<GroupedSelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes)
    {
        name = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        if (String.IsNullOrEmpty(name))
        {
            throw new ArgumentException("Null Or Empty", "name");
        }

        bool usedViewData = false;

        // If we got a null selectList, try to use ViewData to get the list of items.
        if (selectList == null)
        {
            selectList = htmlHelper.GetSelectData(name);
            usedViewData = true;
        }

        object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(name, typeof(string[])) : htmlHelper.GetModelStateValue(name, typeof(string));

        // If we haven't already used ViewData to get the entire list of items then we need to
        // use the ViewData-supplied value before using the parameter-supplied value.
        if (!usedViewData)
        {
            if (defaultValue == null)
            {
                defaultValue = htmlHelper.ViewData.Eval(name);
            }
        }

        if (defaultValue != null)
        {
            IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
            IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture);
            HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
            List<GroupedSelectListItem> newSelectList = new List<GroupedSelectListItem>();

            foreach (GroupedSelectListItem item in selectList)
            {
                item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
                newSelectList.Add(item);
            }
            selectList = newSelectList;
        }

        // Convert each ListItem to an <option> tag
        StringBuilder listItemBuilder = new StringBuilder();

        // Make optionLabel the first item that gets rendered.
        if (optionLabel != null)
        {
            listItemBuilder.AppendLine(ListItemToOption(new GroupedSelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false }));
        }

        foreach (var group in selectList.GroupBy(i => i.GroupKey))
        {
            string groupName = selectList.Where(i => i.GroupKey == group.Key).Select(it => it.GroupName).FirstOrDefault();
            listItemBuilder.AppendLine(string.Format("<optgroup label=\"{0}\" value=\"{1}\">", groupName, group.Key));
            foreach (GroupedSelectListItem item in group)
            {
                listItemBuilder.AppendLine(ListItemToOption(item));
            }
            listItemBuilder.AppendLine("</optgroup>");
        }

        TagBuilder tagBuilder = new TagBuilder("select")
        {
            InnerHtml = listItemBuilder.ToString()
        };
        tagBuilder.MergeAttributes(htmlAttributes);
        tagBuilder.MergeAttribute("name", name, true /* replaceExisting */);
        tagBuilder.GenerateId(name);
        if (allowMultiple)
        {
            tagBuilder.MergeAttribute("multiple", "multiple");
        }

        // If there are any errors for a named field, we add the css attribute.
        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState))
        {
            if (modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
        }

        return MvcHtmlString.Create(tagBuilder.ToString());
    }

    internal static object GetModelStateValue(this HtmlHelper helper, string key, Type destinationType)
    {
        ModelState modelState;
        if (helper.ViewData.ModelState.TryGetValue(key, out modelState))
        {
            if (modelState.Value != null)
            {
                return modelState.Value.ConvertTo(destinationType, null /* culture */);
            }
        }
        return null;
    }

}

Coordinator
Feb 28, 2011 at 10:24 AM

Hi Thanks for the proposal,

It is an interesting extension of the dropdown. I was already considering extensions of ListBox and DropDowns where instead of specifying the field to be used as string one could specify them with lambda expressions, instead.

This is a further feature that is interesting to add. However, I would like to reflect a little time more on all features it is worth to add to a DropDown. Thus I don'think I will insert this in the 0.9 alfa that will be released in a few days

but directly in the 1.0 beta...together with something future more...I hope. If you have further features ...pls doesn't esitate to propose them to me.

Feb 28, 2011 at 1:42 PM

Hi

Idea 1

maybe you can do one feature called universal controller who can build its element from an template model or some sort of plugin extension this way its possible to create new controls driven from controls toolkit in the future.

maybe this seams big i don't know but if this thing exists of some sort then the control toolkit can grow its controls with the help of others.

my idea is like control toolkit can have one website library with controls or extensions to existing controls who can be downloaded and plugged into the toolkit.

 

Idea 2

one control who is like bound to one database or rss feed and can display news ore whatever is in the data container with support for template.

 

will try to think of new possible controls its not so easy when most of them already exists :)

Coordinator
Mar 6, 2011 at 2:07 PM

About your New Controls Ideas:

Idea 1. Controls have nothing to do with Controller. All my controls don't need the help of the controller. They just allow display/editing of items contained in the ViewModel passed from the any controller to the View.

My controls don' works like several other control suites based on already existing Javascript libraries that needs controllers that help controls to communicate with the server via ajax. If you want you can use ajax..

.but you are not forced to do it! My Datagrid for example just allows the user edit records passed as a collection of the ViewModel...You do your job in the View and than you post your Grid, normally or via Ajax..

.The View Model is updated automatically by the Mvc Controls Toolkit Engine. Read more about the theory behind the Mvc Controls Toolkit:

http://mvccontrolstoolkit.codeplex.com/wikipage?title=Foundations%20of%20the%20Mvc%20Controls%20Toolkit

Pligins with new controls can already be implemented using the "Core features" of the Mvc Controls Toolkit as explained here and here.

 

Idea 2. Accessind directly the database from a control in a View is against the separation of concerns between the Layers that MVC is founced on...Data need to be passed through a ViewModel before reaching the View.

However the Idea of a "Gadget" that is able to connect either to an rss Feed or to a WebService is interesting. In such a case the Feed or the WebService might be an alternative to a child controller. 

What about writing yourself a plugin to allows this? If you want to do it I am available to furnish technical support and help.

Coordinator
Apr 10, 2011 at 1:41 PM

I implemeted the dropdown with grouping and other interesting features... see the announcement of the new incoming 1.0 beta here: http://mvccontrolstoolkit.codeplex.com/. In a few days the new version will be available for download.

Nov 6, 2012 at 9:34 AM

Multi select child nodes in the treeview

I would like to know if it is possible to allow users to select multiple elements inside a treeview section and then move them into any other section. Right now user needs to move the individual section by drag drop mechanism.

 

For example

Root

  -Section 1

      -document 1

      -document 2

      -document 3

 -Section 2

now i want to be able to select document 2 and document 3 and move them together into Section 2.

this will help in case where the section 1 contains around 100 documents and i want to move around 40 documents of similar types into a new section.