Поддержка ViewState в MVC ViewUserControl - PullRequest
0 голосов
/ 15 сентября 2011

Я знаю, я знаю, это идет против зерна.Прежде чем все захотят читать лекции о модели MVC, это крайняя мера.У меня есть элемент управления ASP.NET, который я должен получить для работы в MVC, который требует ViewState и был бы признателен, чтобы сосредоточиться на этом.Я знаю, что могу загрузить классические страницы ASP.NET в MVC с помощью хитрости маршрутов , но мне нужно интегральное решение, которое вписывается в структуру MVC.

Должно бытьспособ расширить ViewUserControl, чтобы играть вместе с игрой ViewState, или фильтром или атрибутом, или даже насмехаться над объектом ViewState, анализируя запрос и каким-то образом переопределяя что-то в начале конвейера, чтобы вызвать LoadViewState.

Увы, боюсь, я недостаточно разбираюсь в классическом ASP.NET, чтобы знать, как это сделать.ViewUserControl имеет свойство ViewState, полученное из объекта UserControl вместе с методами 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 никогда не делает.

Ответы [ 3 ]

0 голосов
/ 16 сентября 2011

Telerik поддерживает свои RadControls в среде MVC; Я использовал несколько из них. Вы можете найти сообщение в блоге здесь: http://blogs.telerik.com/aspnetmvcteam/posts/08-11-06/asp_net_ajax_controls_in_asp_net_mvc.aspx

Я не делал этого недавно, так как они выпустили MVC-фреймворк с открытым исходным кодом. Однако они выпустили набор вспомогательных расширений для использования своих элементов управления в MVC, который должен быть где-то доступен.

Так что это не должно быть проблемой. У них также был пример демонстрации с использованием элементов управления ASP.NET AJAX в MVC, доступных здесь: http://www.telerikwatch.com/2009/01/telerik-mvc-demo-app-now-available.html

НТН.

0 голосов
/ 16 сентября 2011

Все вы, кто входит сюда, не оставляйте надежду. Я смог найти решение для этого, хотя это не очень красиво. Он использует небольшое отражение и жестко закодированное отображение дерева объектов. Надеюсь, это будет хорошей отправной точкой для тех, кому нужен ViewState в MVC.

Частичное представление:

<%@ 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;
        }
    }
}
0 голосов
/ 15 сентября 2011

Вы пытаетесь вписать квадратный колышек в круглое отверстие, но ....

Чтобы ViewState работал со всей составленной страницей (контент + мастер + элементы управления), необходимо иметь <form runat="server"> упаковка всех элементов, которые требуют ViewState.А в WebForms вы можете иметь только один из них на странице.Ваш элемент управления должен находиться на той же странице, на которой есть этот элемент формы.Если вы помещаете это во что-то, что вызывается с помощью RenderPartial и т. Д., То это, вероятно, не будет работать.Например, если оно у вас в нужном месте, вам может потребоваться, чтобы дополнительные события страницы вызывались для сохранения / загрузки состояния просмотра.И даже после того, как вы начнете работать, обеспечить правильную работу событий щелчка на стороне элемента управления будет еще сложнее.

Я знаю, что вы не хотите это слышать, но в долгосрочной перспективе будет лучшеиспользовать страницу WebForms или переписать вещи, чтобы использовать компонент, разработанный для Mvc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...