我知道我知道,这是违背常理的。在每个人都想讲解MVC模式之前,这是一个极端的措施。我有一个ASP.NET控件,我必须在需要ViewState的MVC中工作,如果能专注于此将不胜感激。我知道我可以使用load a classic ASP.NET pages in MVC by a trick of routes,但我需要一个适合MVC框架的完整解决方案。
必须有一种方法来扩展ViewUserControl以配合ViewState游戏,或者通过过滤器或属性,甚至通过解析请求并以某种方式覆盖管道中的早期内容来调用LoadViewState来模拟ViewState对象。
遗憾的是,我对经典的ASP.NET还不够精通,不知道如何做到这一点。ViewUserControl具有从UserControl对象派生的ViewState属性,以及SaveViewState和LoadViewState方法,因此我看到了这样做的一些希望。
这是我到目前为止所知道的:
<%@ Control Language="C#" CodeBehind="RadGridExample.ascx.cs" Inherits="MvcApplication5.Views.Shared.RadGridExample" %>
<form runat="server">
<telerik:RadScriptManager ID="scriptmanager2" runat="server"></telerik:RadScriptManager>
<telerik:RadGrid runat="server" ID="RadGrid1" AutoGenerateColumns="false" AllowMultiRowSelection="true" ShowGroupPanel="true">
<MasterTableView TableLayout="Fixed" >
<Columns>
<telerik:GridBoundColumn DataField="Name" HeaderText="Name" DataType="System.String" />
<telerik:GridBoundColumn DataField="Age" HeaderText="Age" DataType="System.String" />
</Columns>
</MasterTableView>
<ClientSettings AllowDragToGroup="true" >
</ClientSettings>
</telerik:RadGrid>
</form>局部视图的代码幕后:
namespace MvcApplication5.Views.Shared
{
public class RadGridExample : ViewUserControl
{
protected void Page_Init()
{
HomeIndexViewModel viewModel = this.Model as HomeIndexViewModel;
RadGrid grid = this.Controls[0].FindControl("RadGrid1") as RadGrid;
grid.DataSource = viewModel.Animals;
grid.DataBind();
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
}
protected override object SaveViewState()
{
return base.SaveViewState();
}
}
}有趣的是,SaveViewState会被调用,但LoadViewState永远不会调用。
发布于 2011-09-16 19:57:59
你们所有进入这里的人,不要放弃希望。我找到了一个解决方案,尽管它不是很漂亮。它使用少量的反射和硬编码映射到对象树。希望这对任何需要在MVC中使用ViewState的人来说是一个很好的起点。
局部视图:
<%@ Control Language="C#" CodeBehind="RadGridExample.ascx.cs" Inherits="MvcApplication5.Views.Shared.RadGridExample" %>
<form runat="server">
<telerik:RadScriptManager ID="scriptmanager2" runat="server"></telerik:RadScriptManager>
<telerik:RadGrid runat="server" ID="RadGrid1" AutoGenerateColumns="false" AllowMultiRowSelection="true" ShowGroupPanel="true" AllowFilteringByColumn="True" >
<MasterTableView TableLayout="Fixed" >
<Columns>
<telerik:GridBoundColumn DataField="Name" HeaderText="Name" DataType="System.String" />
<telerik:GridBoundColumn DataField="Age" HeaderText="Age" DataType="System.String" />
</Columns>
</MasterTableView>
<ClientSettings AllowDragToGroup="true" AllowGroupExpandCollapse="false" >
</ClientSettings>
</telerik:RadGrid>
</form>代码隐藏:
using System.Reflection;
using System.Web.Mvc;
using System.Web.UI;
using MvcApplication5.Models.ViewModels;
using Telerik.Web.UI;
namespace MvcApplication5.Views.Shared
{
public class RadGridExample : ViewUserControl
{
protected void Page_Init()
{
RadGrid grid = this.Controls[0].FindControl("RadGrid1") as RadGrid;
grid.NeedDataSource += new GridNeedDataSourceEventHandler(grid_NeedDataSource);
grid.DataBind();
string viewState = Request.Form["__VIEWSTATE"];
if (!string.IsNullOrEmpty(viewState))
{
LosFormatter formatter = new LosFormatter();
object savedStateObject = formatter.Deserialize(viewState);
MethodInfo method = grid.GetType().GetMethod("LoadViewState", BindingFlags.NonPublic | BindingFlags.Instance);
// TODO: Find a less brittle/more elegant way to isolate the appropiate viewstate object for this control
// In the case of Telerik's RadGrid, the key wasy find the tree that had an array of 13 objects
method.Invoke(grid, new object[] { (((((((((savedStateObject as Pair).First as Pair).Second as Pair).Second as System.Collections.ArrayList)[1] as Pair).Second as System.Collections.ArrayList)[1] as Pair).Second as System.Collections.ArrayList)[1] as Pair).First });
}
string eventArgument = Request.Form["__EVENTARGUMENT"];
if (!string.IsNullOrEmpty(eventArgument))
{
grid.RaisePostBackEvent(eventArgument);
}
}
void grid_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
(sender as RadGrid).DataSource = this.Model as HomeIndexViewModel;
}
}
}发布于 2011-09-16 03:48:19
你在试着把一个方形的钉子插进一个圆孔里,但是....
要让ViewState工作,您的整个合成页面(内容+母版+控件)需要有一个包装所有需要ViewState的元素的<form runat="server">。而在WebForms中,一个页面中只能包含其中的一个。您的控件应该位于具有该表单元素的同一页中。如果你把它放在使用RenderPartial等调用的东西中,那么它可能不会工作。即使您将它放在正确的位置,也必须确保调用额外的页面事件来持久化/加载视图状态。而且,即使这样做了,确保控件的服务器端单击事件正常工作也可能更加困难。
我知道你不想听到它,但从长远来看,使用WebForms页面或重写代码来使用为Mvc设计的组件会更好。
发布于 2011-09-16 06:16:05
Telerik在MVC框架中支持他们的RadControls;我使用了其中的一些。你可以在这里找到博客文章:http://blogs.telerik.com/aspnetmvcteam/posts/08-11-06/asp_net_ajax_controls_in_asp_net_mvc.aspx
自从他们发布了开源的MVC框架后,我最近就没有这样做过。然而,他们已经发布了一组助手扩展,以便在MVC中使用他们的控件,这些扩展应该在某个地方可用。
所以这应该不是问题。他们还提供了一个使用MVC中的ASP.NET AJAX控件的示例演示,可在此处获得:http://www.telerikwatch.com/2009/01/telerik-mvc-demo-app-now-available.html
HTH。
https://stackoverflow.com/questions/7435738
复制相似问题