首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在MVC ViewUserControl中支持ViewState

在MVC ViewUserControl中支持ViewState
EN

Stack Overflow用户
提问于 2011-09-16 02:35:44
回答 3查看 1K关注 0票数 0

我知道我知道,这是违背常理的。在每个人都想讲解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方法,因此我看到了这样做的一些希望。

这是我到目前为止所知道的:

代码语言:javascript
复制
<%@ 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>

局部视图的代码幕后:

代码语言:javascript
复制
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永远不会调用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-16 19:57:59

你们所有进入这里的人,不要放弃希望。我找到了一个解决方案,尽管它不是很漂亮。它使用少量的反射和硬编码映射到对象树。希望这对任何需要在MVC中使用ViewState的人来说是一个很好的起点。

局部视图:

代码语言:javascript
复制
<%@ 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>

代码隐藏:

代码语言:javascript
复制
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;
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2011-09-16 03:48:19

你在试着把一个方形的钉子插进一个圆孔里,但是....

要让ViewState工作,您的整个合成页面(内容+母版+控件)需要有一个包装所有需要ViewState的元素的<form runat="server">。而在WebForms中,一个页面中只能包含其中的一个。您的控件应该位于具有该表单元素的同一页中。如果你把它放在使用RenderPartial等调用的东西中,那么它可能不会工作。即使您将它放在正确的位置,也必须确保调用额外的页面事件来持久化/加载视图状态。而且,即使这样做了,确保控件的服务器端单击事件正常工作也可能更加困难。

我知道你不想听到它,但从长远来看,使用WebForms页面或重写代码来使用为Mvc设计的组件会更好。

票数 0
EN

Stack Overflow用户

发布于 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。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7435738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档