在动态创建的Html.AutoCompleteFor

时间:2016-02-23 20:29:03

标签: c# asp.net-mvc typeahead.js

我正在使用timdwilson的预先package。不幸的是,当我将AutoCompleteFor框放在for循环中时,我遇到了一个问题,因为lambda表达式与AutocompleteHelpers类(特别是Expression求值程序不匹配)。

基本上,我不是model => model.SelectedIngredeints[i]而是model => model.SelectedIngredients.get_Item(value(ASP._Page_Views_Recipes_Create_cshtml+<>c__DisplayClass3_0).i)

无论如何,C#可以评估SelectedIngredients.get_Item(value(ASP._Page_Views_Recipes_Create_cshtml+<>c__DisplayClass3_0).i只是SelectedIngredients[i]吗?

如果我不清楚,这里有一些屏幕截图......

这里没有问题,因为model => model.testInt已被(?)评估或引用。

enter image description here enter image description here

但是,当我尝试使用我的迭代器时,会发生以下情况。

enter image description here enter image description here

1 个答案:

答案 0 :(得分:3)

我是timdwilson,我创建了你遇到麻烦的Twitter.Typeahead.MVC.Model NuGet包和typeahead-mvc-model GitHub存储库。在查看了您的问题之后,我发现确实,data-autocomplete-id-field为输入元素的AutocompleteFor属性生成的HTML应该是SelectedIngredients_0_,而是SelectedIngredients.get_Item(value(ASP._Page_Views_Recipes_Create_cshtml+<>c__DisplayClass3_0).i) }。

换句话说,你期待这个:

<input class="form-control typeahead" data-autocomplete-id-field="SelectedIngredients_12_" data-autocomplete-url="/Recipes/GetIngredients" id="SelectedIngredientsNames_12_" name="SelectedIngredientsNames[12]" type="text" value="" />

但是,相反,得到了这个:

<input class="form-control typeahead" data-autocomplete-id-field="SelectedIngredients.get_Item(value(ASP._Page_Views_Recipes_Create_cshtml+<>c__DisplayClass3_0).i)" data-autocomplete-url="/Recipes/GetIngredients" id="SelectedIngredientsNames_12_" name="SelectedIngredientsNames[12]" type="text" value="" />

由于data-autocomplete-id-field用于在页面上查找此元素并设置其值,因此在选择预先输入值时,永远不会捕获所选的ID。

我通过正确生成HTML来修复此问题,与生成valueExpression的方式相同。此修补程序将显示在Twitter.Typeahead.MVC.Model version 1.0.6 NuGet package中,并且已经签入typeahead-mvc-model GitHub repository

要在本地副本中修复此问题,请使用以下代码替换Controllers \ HtmlHelpers文件夹中的AutocompleteHelpers类(或将其移动到的位置):

public static class HtmlHelpers {

    /// <summary>
    /// Extends MvcHtml to conditionaly display a value or empty string
    /// </summary>
    /// <param name="value">Value to be displayed if 'evaluation' is true</param>
    /// <param name="evaluation"></param>
    /// <returns></returns>
    public static MvcHtmlString If(this MvcHtmlString value, bool evaluation) {
        return evaluation ? value : MvcHtmlString.Empty;
    }

    /// <summary>
    /// Extends MvcHtml to conditionaly display one of two possible values
    /// </summary>
    /// <param name="value">Value to be displayed if 'evaluation' is true</param>
    /// <param name="evaluation"></param>
    /// <param name="valueIfFalse">Value to be displayed if 'evaluation' is false</param>
    /// <returns></returns>
    public static MvcHtmlString If(this MvcHtmlString value, bool evaluation, MvcHtmlString valueIfFalse) {
        return evaluation ? value : valueIfFalse;
    }
}

public static class AutocompleteHelpers
{
    public static MvcHtmlString AutocompleteFor<TModel, TProperty1, TProperty2>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty1>> valueExpression,
        Expression<Func<TModel, TProperty2>> idExpression, string actionName, string controllerName, bool requestFocus)
    {
        return CreateTextBoxForFromAutocompleteFor<TModel, TProperty1, TProperty2>(html, valueExpression, actionName, controllerName, requestFocus,
            idExpression.Body.ToString());
    }

    public static MvcHtmlString AutocompleteFor<TModel, TProperty1, TProperty2>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty1>> valueExpression,
        Expression<Func<TModel, TProperty2>> idExpression, int index, string actionName, string controllerName, bool requestFocus)
    {
        // Get the fully qualified class name of the autocomplete id field
        string idFieldString = idExpression.Body.ToString();

        // handle if the id field is an array
        int loc_get_Item = idFieldString.IndexOf(".get_Item(");
        if (loc_get_Item > 0)
        {
            idFieldString = idFieldString.Substring(0, loc_get_Item);
            idFieldString += string.Format("_{0}_", index);
        }

        var textBoxFor = CreateTextBoxForFromAutocompleteFor<TModel, TProperty1, TProperty2>(html, valueExpression, actionName, controllerName, requestFocus, idFieldString);
        return textBoxFor;
    }

    private static MvcHtmlString CreateTextBoxForFromAutocompleteFor<TModel, TProperty1, TProperty2>(HtmlHelper<TModel> html,
        Expression<Func<TModel, TProperty1>> valueExpression, string actionName, string controllerName, bool requestFocus, string idFieldString)
    {
        string autocompleteUrl = UrlHelper.GenerateUrl(null, actionName, controllerName,
                                                       null,
                                                       html.RouteCollection,
                                                       html.ViewContext.RequestContext,
                                                       includeImplicitMvcValues: true);
        string @class = "form-control typeahead" + (requestFocus ? " focus" : string.Empty);
        // We need to strip the 'model.' from the beginning
        int loc = idFieldString.IndexOf('.');
        // Also, replace the . with _ as this is done by MVC so the field name is js friendly
        string autocompleteIdField = idFieldString.Substring(loc + 1, idFieldString.Length - loc - 1).Replace('.', '_');
        var textBoxFor = html.TextBoxFor(valueExpression,
            new {data_autocomplete_url = autocompleteUrl, @class, data_autocomplete_id_field = autocompleteIdField});
        return textBoxFor;
    }
}

如果此修复程序适合您,请接受此作为您问题的答案。如果您有任何其他问题或疑问,请告诉我。谢谢罗里!