简体   繁体   English

在MVC ViewUserControl中支持ViewState

[英]Supporting ViewState in an MVC ViewUserControl

I know I know, it's going against the grain. 我知道我知道,这与事实相反。 Before everyone wants to lecture about the MVC pattern, this is an extreme measure. 在每个人都想讲授MVC模式之前,这是一个极端的措施。 I have a ASP.NET control that I must get to work in MVC that requires the ViewState and would appreciate the focus to stay on this. 我有一个ASP.NET控件,我必须在需要ViewState的MVC中使用它,并且希望您能专注于此。 I am aware that I can load a classic ASP.NET pages in MVC by a trick of routes , but I need an integral solution that fits within the MVC framework. 我知道可以通过一些技巧在MVC中加载经典的ASP.NET页面 ,但是我需要一个适合MVC框架的整体解决方案。

There must be a way to extend a ViewUserControl to play along with the ViewState game, or by a filter or attribute, or even mocking a ViewState object by parsing the Request and somehow overriding something early in the pipeline to invoke the LoadViewState. 必须有一种方法来扩展ViewUserControl,使其与ViewState游戏一起玩,或者通过过滤器或属性,甚至通过解析Request并以某种方式重写管道中的某些内容来模拟ViewState对象,以调用LoadViewState。

Alas, I'm afraid I'm not versed enough with classic ASP.NET to know how to do this. las,恐怕我对经典的ASP.NET不够精通,不知道该怎么做。 The ViewUserControl has the ViewState property derived from the UserControl object along with SaveViewState and LoadViewState methods, so I see some hope in doing this. ViewUserControl具有从UserControl对象派生的ViewState属性以及SaveViewState和LoadViewState方法,因此我希望这样做。

Here is what I have so far: 这是我到目前为止的内容:

<%@ 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>

The code behind for the partial view: 部分视图的代码如下:

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

Funny thing, the SaveViewState gets called, but LoadViewState never does. 有趣的是,调用了SaveViewState,但从未调用LoadViewState。

You are trying to fit a square peg into a round hole, but.... 您正在尝试将方形钉插入圆孔中,但是...

To get ViewState to work your entire composed page (content + master + controls) requires that you have a <form runat="server"> wrapping all the elements that require ViewState. 为了使ViewState能够工作整个组合页面(内容+主控件+控件),您需要具有一个<form runat="server">包装所有需要ViewState的元素。 And in WebForms you can only have one of those in a page. 在WebForms中,页面中只能包含其中之一。 Your control should be in the same page that has that form element. 您的控件应该在具有该表单元素的同一页中。 If you put it in something that gets called using RenderPartial etc then it probably won't work. 如果将其放在使用RenderPartial等调用的内容中,则可能无法正常工作。 Een if you have it in the right place you might have to ensure that the extra page events get invoked to persist/load the view state. 如果您将它放在正确的位置,则可能必须确保调用额外的页面事件以持久化/加载视图状态。 And even once you get that working ensuring that the control's server-side click events work correctly might be even more difficult. 而且,即使您能够正常工作,要确保控件的服务器端单击事件正常运行,也可能会变得更加困难。

I know you don't want to hear it but in the long run it will be better to use a WebForms page or rewrite things to use a component designed for Mvc. 我知道您不想听,但是从长远来看,使用WebForms页面或重写内容以使用为Mvc设计的组件会更好。

Telerik supports their RadControls in the MVC framework; Telerik在MVC框架中支持其RadControl。 I used a few of them. 我用了一些。 You can find a blog post here: http://blogs.telerik.com/aspnetmvcteam/posts/08-11-06/asp_net_ajax_controls_in_asp_net_mvc.aspx 您可以在此处找到博客文章: http : //blogs.telerik.com/aspnetmvcteam/posts/08-11-06/asp_net_ajax_controls_in_asp_net_mvc.aspx

I haven't done it recently since they released the MVC framework that's open source. 自从他们发布了开源的MVC框架以来,我最近还没有这样做。 However, they had released a set of helper extensions to use their controls in MVC, which should be available somewhere. 但是,他们发布了一组辅助程序扩展以在MVC中使用其控件,这些控件应该可以在某个地方使用。

So this shouldn't be a problem. 因此,这应该不是问题。 They also had a sample demo using the ASP.NET AJAX controls in MVC, available here: http://www.telerikwatch.com/2009/01/telerik-mvc-demo-app-now-available.html 他们还使用MVC中的ASP.NET AJAX控件进行了示例演示,可在以下位置找到http : //www.telerikwatch.com/2009/01/telerik-mvc-demo-app-now-available.html

HTH. HTH。

All ye who enter here, do not abandon hope. 进入这里的所有人,不要放弃希望。 I was able to find a solution to this, though it's not very pretty. 尽管不是很漂亮,但我能够找到解决方案。 It uses a little reflection and hard coded mapping to tree of objects. 它使用一点反射和硬编码映射到对象树。 Hopefully this will be a good starting point for anyone needing ViewState in MVC. 希望对于任何需要在MVC中使用ViewState的人来说,这都是一个很好的起点。

Partial View: 部分视图:

<%@ 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>

Code behind: 后面的代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将ViewUserControl的属性绑定到.NET MVC2中的localvariable - Bind property on ViewUserControl to localvariable in .NET MVC2 带有使用MVC 1.0的控制器的ASP.Net MVC ViewUserControl - ASP.Net MVC ViewUserControl with controller using MVC 1.0 .net mvc ViewPage<t1> 和查看用户控件<t2>行为</t2></t1> - .net mvc ViewPage<T1> and ViewUserControl<T2> behaviour 无法加载类型System.Web.Mvc.ViewUserControl <somethig> - Could not load type System.Web.Mvc.ViewUserControl<somethig> 如果添加按钮,则处于编辑模式的ASP.NET MVC ViewUserControl不起作用 - ASP.NET MVC ViewUserControl in edit mode doesn`t work if a add a button MVC部分控制:“找不到IViewDataContainer对象。 ViewUserControl必须在ViewPage内部,即ViewMasterPage中” - MVC Partial Control: “cannot find an IViewDataContainer object. The ViewUserControl must be inside a ViewPage, a ViewMasterPage” 如何动态编译ViewUserControl(Asp.Net MVC)或Asp.Net控件 - How to dynamically compile a ViewUserControl(Asp.Net MVC) or Asp.Net Control 维护Asp.net mvc中的viewstate? - Maintaining viewstate in Asp.net mvc? 在ASP.NET MVC中支持WCF - Supporting WCF in ASP.NET MVC ASP.NET MVC如何从应用程序中删除ViewState? - How ASP.NET MVC removes ViewState from application?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM