在动态创建中使用 typeahead-mvc-model Html.AutoCompleteFor
using typeahead-mvc-model in dynamically created Html.AutoCompleteFor
我正在使用来自 timdwilson 的 typeahead package。不幸的是,当我将 AutoCompleteFor
框放在 for 循环中时,我 运行 遇到了问题,因为 lambda 表达式不能很好地与 AutocompleteHelpers
class (特别是, 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
已经(?)评估或引用了。
但是,当我尝试使用我的迭代器时,会发生以下情况。
我是 timdwilson,我创建了您遇到问题的 Twitter.Typeahead.MVC.Model NuGet 包和 typeahead-mvc-model GitHub 存储库。在查看您的问题后,我发现 AutocompleteFor
为输入元素的 data-autocomplete-id-field
属性生成的 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 and it has already been checked in to the typeahead-mvc-model GitHub repository.
要在您的本地副本中修复此问题,请将 Controllers\HtmlHelpers 文件夹(或您将其移动到的任何位置)中的 AutocompleteHelpers class 替换为以下代码:
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;
}
}
如果此修复对您有效,请接受此作为您问题的答案。如果您有任何其他问题或困难,请告诉我。谢谢罗里!
我正在使用来自 timdwilson 的 typeahead package。不幸的是,当我将 AutoCompleteFor
框放在 for 循环中时,我 运行 遇到了问题,因为 lambda 表达式不能很好地与 AutocompleteHelpers
class (特别是, 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
已经(?)评估或引用了。
但是,当我尝试使用我的迭代器时,会发生以下情况。
我是 timdwilson,我创建了您遇到问题的 Twitter.Typeahead.MVC.Model NuGet 包和 typeahead-mvc-model GitHub 存储库。在查看您的问题后,我发现 AutocompleteFor
为输入元素的 data-autocomplete-id-field
属性生成的 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 and it has already been checked in to the typeahead-mvc-model GitHub repository.
要在您的本地副本中修复此问题,请将 Controllers\HtmlHelpers 文件夹(或您将其移动到的任何位置)中的 AutocompleteHelpers class 替换为以下代码:
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;
}
}
如果此修复对您有效,请接受此作为您问题的答案。如果您有任何其他问题或困难,请告诉我。谢谢罗里!