我知道我知道,这与谷物有关。在每个人都想要讲述MVC模式之前,这是一个极端的措施。我有一个ASP.NET控件,我必须在MVC中工作,需要ViewState,并希望重点留在此。我知道我可以load a classic ASP.NET pages in MVC by a trick of routes,但我需要一个适合MVC框架的完整解决方案。
必须有一种方法可以扩展ViewUserControl以与ViewState游戏一起播放,或者通过过滤器或属性,甚至通过解析请求来模拟ViewState对象,并以某种方式覆盖管道中的某些东西以调用LoadViewState。
唉,我担心我不熟悉经典的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永远不会。
答案 0 :(得分:0)
你正试图将方形钉固定在一个圆孔中,但是......
要使ViewState工作,整个组合页面(内容+主控+控件)要求您有<form runat="server">
包装所有需要ViewState的元素。在WebForms中,您只能在页面中拥有其中一个。您的控件应该位于具有该表单元素的同一页面中。如果你把它放在使用RenderPartial等调用的东西中,那么它可能无法工作。如果您将它放在正确的位置,您可能必须确保调用额外的页面事件以保持/加载视图状态。甚至一旦你确保控件的服务器端点击事件正常工作可能会更加困难。
我知道您不想听,但从长远来看,最好使用WebForms页面或重写内容以使用专为Mvc设计的组件。
答案 1 :(得分:0)
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。
答案 2 :(得分:0)
所有进入这里的人,都不要放弃希望。我能够找到解决方案,虽然它不是很漂亮。它使用一点反射和硬编码映射到对象树。希望这对于需要在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;
}
}
}