我希望能以通用的方式从控制器中获取视图并集中于特定的模型属性。
目前我已经有了以下内容:
控制器:
// To become an extension/base class method
private void FocusOnField<TModel, TProperty>(Expression<Func<TModel, TProperty>> fieldExpression)
{
ViewData["FieldToFocus"] = fieldExpression;
}
...
FocusOnField((ConcreteModelClass m) => m.MyProperty);
View
public static class ViewPageExtensions
{
public static MvcHtmlString FocusScript<TModel>(this ViewPage<TModel> viewPage)
{
if (viewPage.ViewData["FieldToFocus"] != null)
{
return MvcHtmlString.Create(
@"<script type=""text/javascript"" language=""javascript"">
$(document).ready(function() {
setTimeout(function() {
$('#" + viewPage.Html.IdFor((System.Linq.Expressions.Expression<Func<TModel, object>>)viewPage.ViewData["FieldToFocus"]) + @"').focus();
}, 500);
});
</script>");
}
else
{
return MvcHtmlString.Empty;
}
}
}
我现在面临的问题是,在视图的FocusScript
方法中,我不知道要聚焦的属性的返回类型,对于任何不返回对象的属性进行强转(System.Linq.Expressions.Expression<Func<TModel, object>>)
都会失败。
我不能只为该属性添加第二个泛型参数,因为我不知道控制器想让我关注的属性的返回类型是什么。
如何以通用的方式编写我的视图扩展方法FocusScript
,使其可以与返回类型各异的属性一起使用?
为什么会有问题?
我知道我可以只传递我想要聚焦的控件的 Id 到控制器中,并让 JavaScript 读取该 Id,找到控件并将其聚焦。但是,我不喜欢在控制器中硬编码属于视图的东西(控件的 Id)。我想告诉方法我想要的属性,它应该像视图通常获取/创建控件的 Id 一样知道要使用的 Id。
假设我有一个模型:
class MyModel
{
public int IntProperty { get; set; }
public string StringProperty { get; set; }
}
在控制器的不同位置,我希望集中关注不同的字段:
FocusOnField((MyModel m) => m.IntProperty);
...
FocusOnField((MyModel m) => m.StringProperty);
现在,在第一种情况下,表达式是一个返回整数的函数,在第二种情况下,它返回一个字符串。因此,我不知道该将我的ViewData["FieldToFocus"]转换成什么类型(以便将其传递给IdFor<>()
),因为它基于属性而变化..
FocusScript
方法吗?我还不确定它如何工作,因为控制器可能想要绑定到该模型上的许多不同属性(具有不同的返回类型)。如果您认为它可以工作,我会很感激您提供一个代码示例,也许我理解得不正确。 - George DuckettFocusScript
方法内部使用反射解决,以使用正确的泛型参数调用IdFor
,但我还无法完全理解它。 - George Duckett