gpt4 book ai didi

c# - 将模型属性表达式传递给 View

转载 作者:太空狗 更新时间:2023-10-29 20:21:15 25 4
gpt4 key购买 nike

我希望有一种方法可以让 View 以通用方式关注来自 Controller 的特定模型属性。

我目前拥有的是:


Controller :

// 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);

查看

    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;
}
}
}

我现在面临的问题是,在 View 的 FocusScript 中方法 我不知道要关注的属性的返回类型,并转换为 (System.Linq.Expressions.Expression<Func<TModel, object>>)任何不返回对象的属性都会失败。

我不能只为属性添加第二个通用参数,因为我不知道 Controller 希望我关注的属性的返回类型是什么。

如何编写我的 View 扩展方法 FocusScript以一种通用的方式,以便它可以与不同返回类型的属性一起使用?


为什么会出现问题?

我知道我可以在 Controller 中传递我想要关注的控件的 ID,然后让 javascript 读取该 ID,找到该控件并关注它。但是,我不喜欢在 Controller 中硬编码属于 View 的内容(控件的 ID)。我想告诉方法我想要什么属性,它应该知道要使用的 Id,就像 View 通常获取/创建控件的 Id 一样。

假设我有一个模型:

class MyModel
{
public int IntProperty { get; set; }
public string StringProperty { get; set; }
}

在 Controller 的不同地方我想关注一个不同的领域:

FocusOnField((MyModel m) => m.IntProperty);
...
FocusOnField((MyModel m) => m.StringProperty);

现在,在第一种情况下,表达式是一个返回整数的函数,在第二种情况下,它返回一个字符串。结果,我不知道将我的 ViewData["FieldToFocus"] 转换到什么(将其传递给 IdFor<>() ),因为它因属性而异..

最佳答案

我想我已经找到了解决您问题的方法 - 它适用于我的环境,但我不得不猜测您的代码可能看起来如何。

public static class ViewPageExtensions
{
public static MvcHtmlString GetIdFor<TViewModel, TProperty>(ViewPage<TViewModel> viewPage, Expression<Func<TViewModel, TProperty>> expression)
{
return viewPage.Html.IdFor(expression);
}

public static MvcHtmlString FocusScript<TViewModel>(this ViewPage<TViewModel> viewPage)
{
if (viewPage.ViewData["FieldToFocus"] == null)
return MvcHtmlString.Empty;

object expression = viewPage.ViewData["FieldToFocus"];

Type expressionType = expression.GetType(); // expressionType = Expression<Func<TViewModel, TProperty>>
Type functionType = expressionType.GetGenericArguments()[0]; // functionType = Func<TViewModel, TProperty>
Type[] functionGenericArguments = functionType.GetGenericArguments(); // functionGenericArguments = [TViewModel, TProperty]
System.Reflection.MethodInfo method = typeof(ViewPageExtensions).GetMethod("GetIdFor").MakeGenericMethod(functionGenericArguments); // method = GetIdFor<TViewModel, TProperty>

MvcHtmlString id = (MvcHtmlString)method.Invoke(null, new[] { viewPage, expression }); // Call GetIdFor<TViewModel, TProperty>(viewPage, expression);

return MvcHtmlString.Create(
@"<script type=""text/javascript"" language=""javascript"">
$(document).ready(function() {
setTimeout(function() {
$('#" + id + @"').focus();
}, 500);
});
</script>");
}
}

也许有更优雅的方法,但我认为它归结为您试图将对象(即 ViewData["FieldToFocus"] 的返回类型)转换为正确的表达式树 Expression<Func<TViewModel, TProperty>>但正如您所说,您不知道 TProperty 应该是什么。

另外,为了完成这项工作,我必须向 GetIdFor 添加另一个静态方法。因为目前我不太确定如何调用扩展方法。它只是一个包装器来调用 IdFor扩展方法。

你可以让它不那么冗长(但可能不那么可读)。

object expression = viewPage.ViewData["FieldToFocus"];

MethodInfo method = typeof(ViewPageExtensions).GetMethod("GetIdFor")
.MakeGenericMethod(expression.GetType().GetGenericArguments()[0].GetGenericArguments());

MvcHtmlString id = (MvcHtmlString)method.Invoke(null, new[] { viewPage, expression });

最后一个想法,HtmlHelper.IdFor 的输出不同于ExpressionHelper.GetExpressionText ? IdFor我不是很懂,不知道它会不会一直给你一个匹配属性名的字符串。

ViewData["FieldToFocus"] = ExpressionHelper.GetExpressionText(fieldExpression);

关于c# - 将模型属性表达式传递给 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11450774/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com