我怎样才能重新实例动态ASP.NET用户控件不使用数据库?(How can I re-instant

2019-07-03 14:44发布

我目前正在与使用动态的Web用户控件,我有一点麻烦搞清楚使用ViewState的或不一些其他的方法来重新实例上回发的控件的最好方法我的应用程序的一部分工作要求我在每次回发查询数据库。

基本上我有我的网页上是包含面板抱着孩子的用户控制的可变量的用户控件和一个按钮,上面写着“添加控制”,其功能是非常自我解释。

孩子的用户控件是非常简单的; 它只是一个删除按钮,下拉,并排成一排一个时间选择器控制。 每当用户点击父控制添加控制按钮,一个新的“行”被加入到含有子控制面板。

我想这样做是为了能够添加和删除控件到此集合,修改值,并执行我需要“内存”做,而不必做一个数据库,任何调用任何操作。 当我做添加控件和填充他们的价值观,我想点击“保存”,从控制所有的数据保存/更新到数据库一次。 目前,我已经找到了唯一的解决方案是将数据库中的数据只需保存每个帖子后面,然后使用存储在数据库中的行重新实例上回发的控制。 显然,这种强制用户更改保存到数据库违背自己的意愿,并在他们要取消与控制工作,不保存自己的数据的情况下,额外的工作必须完成,以确保以前犯下的行被删除。

从我所了解使用动态控制,我知道这是最好的在生命周期的初始化阶段将控件添加到页面,然后填充他们的价值观在负载阶段。 我还了解到,以确保您能坚持控件的视图状态的唯一途径是确保你给每个动态控制一个唯一的ID,并确保重新实例化控制时,分配给它的确切相同的ID。 我还了解到,ViewState的不实际加载,直到在生命周期的初始化阶段之后。 这就是我的问题所在。 如何存储和检索这些控件的名字,如果我不能使用视图状态,我不希望执行对数据库的任何电话? 这算哪门子采用ASP.net值甚至可以在内存中的操作/批节能的?

任何帮助是极大的赞赏,

麦克风

Answer 1:

你可以存储你所需要知道的重建在会议期间举行的集合在对照一下最低限度。 会议期间,页面的初始化阶段是可用的。

下面是一个例子。 它包括:

Default.aspx的,CS
- 面板存储用户控制
- “添加控制按钮”,这将在每次点击一次添加一个用户控件

TimeTeller.ascx,CS
- 有一个称为SETTIME方法,其设置在控制到指定时间标签。

Default.aspx的

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DynamicControlTest._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Panel ID="pnlDynamicControls" runat="server">
        </asp:Panel>
        <br />
        <asp:Button ID="btnAddControl" runat="server" Text="Add User Control" 
            onclick="btnAddControl_Click" />
    </div>
    </form>
</body>
</html>

Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DynamicControlTest
{
   public partial class _Default : System.Web.UI.Page
   {
      Dictionary<string, string> myControlList; // ID, Control ascx path

      protected void Page_Load(object sender, EventArgs e)
      {

      }

      protected override void OnInit(EventArgs e)
      {
         base.OnInit(e);

         if (!IsPostBack)
         {
            myControlList = new Dictionary<string, string>();
            Session["myControlList"] = myControlList;
         }
         else 
         {
            myControlList = (Dictionary<string, string>)Session["myControlList"];

            foreach (var registeredControlID in myControlList.Keys) 
            {
               UserControl controlToAdd = new UserControl();
               controlToAdd = (UserControl)controlToAdd.LoadControl(myControlList[registeredControlID]);
               controlToAdd.ID = registeredControlID;

               pnlDynamicControls.Controls.Add(controlToAdd);
            }
         }
      }

      protected void btnAddControl_Click(object sender, EventArgs e)
      {
         UserControl controlToAdd = new UserControl();
         controlToAdd = (UserControl)controlToAdd.LoadControl("TimeTeller.ascx");

         // Set a value to prove viewstate is working
         ((TimeTeller)controlToAdd).SetTime(DateTime.Now);
         controlToAdd.ID = Guid.NewGuid().ToString(); // does not have to be a guid, just something unique to avoid name collision.

         pnlDynamicControls.Controls.Add(controlToAdd);

         myControlList.Add(controlToAdd.ID, controlToAdd.AppRelativeVirtualPath);
      }
   }
}

TimeTeller.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TimeTeller.ascx.cs" Inherits="DynamicControlTest.TimeTeller" %>
<asp:Label ID="lblTime" runat="server"/>

TimeTeller.ascx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DynamicControlTest
{
   public partial class TimeTeller : System.Web.UI.UserControl
   {
      protected void Page_Load(object sender, EventArgs e)
      {

      }

      public void SetTime(DateTime time) 
      {
         lblTime.Text = time.ToString();
      }

      protected override void LoadViewState(object savedState)
      {
         base.LoadViewState(savedState);
         lblTime.Text = (string)ViewState["lblTime"];
      }

      protected override object SaveViewState()
      {
         ViewState["lblTime"] = lblTime.Text;
         return base.SaveViewState();
      }
   }
}  

正如你所看到的,我还是要管理我的用户控件的内部视图状态,但视图状态的包被保存到页面,并交还给上回发的控制。 我认为,需要注意的是我的解决方案是非常接近大卫是非常重要的。 在我的例子唯一的主要区别是,它使用会话,而不是视图状态来存储控制信息。 这样的事情在初始化阶段发生。 需要注意的是该解决方案占用了更多的服务器资源是非常重要的,因此,它可能不会在根据您的缩放策略某些情况下适当的。



Answer 2:

我在过去做到了这一点。 我还没有做到这一点,因为.NET的1.1天,但主要去除相同。

我做这件事是没有的Page_Load初始化重新加载您在最后一页周期创建的控件。

首先,你需要跟踪你在每个页面周期创建控件。 这包括类型,名称等。 。

然后在每个页面加载,你需要重建他们。

你这样做,通过重新创建的控制,assinging它完全相同的ID,将其添加到最终在ViewState [“LoadedControl”]将控制类型的页面上,并且SAMPE地方。

下面是我使用的代码,我只能用我创建的用户控件这样做。 我还没有与ASP.NET控件试过,但我认为它会工作相同。

在这种情况下,我有三胞胎的ArrayList(记住这是.NET 1.1)ADN的第一个项目是一个综合浏览量ID。 您可能不需要,对于您的应用程序。

protected void Page_Load(object sender, System.EventArgs e)
{
    //**********************************************************
    //*  dynCtlArray will hold a triplet with the PageViewID,  *
    //*  ControlID, and the Control Name                       *
    //**********************************************************

    ArrayList dynCtlArray = (ArrayList)this.ViewState["dynCtlArray"];
    if (dynCtlArray != null)
    {

        foreach (object obj in dynCtlArray)
        {
            Triplet ctrlInfo = (Triplet)obj;

            DynamicLoadControl(ctrlInfo);
        }
    }
}

private void DynamicLoadControl(Triplet ctrlInfo)
{
    // ERROR HANDLING REMOVED FOR ANSWER BECAUSE IT IS NOT IMPORTANT YOU SHOULD HANDLE ERRORS IN THIS METHOD

    Control ctrl = this.LoadControl(Request.ApplicationPath
        + "/UC/" + (string)ctrlInfo.Third);

    ctrl.ID = (string)ctrlInfo.Second;

    // Create New PageView Item
    Telerik.WebControls.PageView pvItem = this.RadMultiPage1.PageViews[(int)ctrlInfo.First];
    pvItem.Controls.Add(ctrl);

    /******************************************************
     *  The ControlName must be preserved to track the    *
     *  currently loaded control                          *
     * ****************************************************/
    ViewState["LoadedControl"] = (string)ctrlInfo.Third;
}
private void RegisterDynControl(Triplet trip)
{
    ArrayList dynCtlArray = (ArrayList)this.ViewState["dynCtlArray"];

    if (dynCtlArray == null)
    {
        dynCtlArray = new ArrayList();
        this.ViewState.Add("dynCtlArray", dynCtlArray);
    }

    dynCtlArray.Add(trip);

}

在你的页面上的一些方法

// Create new Control
Control ctrl = Page.LoadControl("../UC/MyUserControl.ascx");

// . . . snip .. . 

// Create Triplet
Triplet ctrlInfo = new Triplet(0, ctrl.ID, "MyUserControl.ascx");
// RegisterDynControl to ViewState
RegisterDynControl(ctrlInfo);

// . . . snip .. . 

要访问控制,以保存有信息,你必须做一个this.Page.FindControl('');



Answer 3:

我实现了一个页面非常相似,丹尼尔的例子,但不能使用Session由于技术限制。 然而,我发现,通过使用领域的一页,我会回来后和Page_Init事件中检索其值。



文章来源: How can I re-instantiate dynamic ASP.NET user controls without using a database?