ASP.NET动态修改控制树

时间:2011-07-21 17:04:06

标签: c# .net asp.net

我正在尝试删除并动态添加控件到我的控制树。例如:

在特定情况下,我打电话:

    private void resetPanel()
    {
        Panel.Controls.Clear();
        Panel.Controls.Add(Image);
        Panel.Controls.Add(HiddenField);
    }

我的主要目标是如何让所添加的控件在回发中保持不变?

当我使用文本框和标题调用另一个类似的函数时,它会完美地存在。但是,对于图像,它会丢失其URL和属性。

我知道要保持动态控件,你必须在Init上添加它,你必须负责控制树,因此需要在每次回发时将动态控件添加到树中。

那么为什么它适用于文章框和标签在帖子后面保持不变但你不能为图像和隐藏字段添加控件?

谢谢, 布赖恩

- 更新和解决方案 -

我在我的代码中发现了一个错误,并且HiddenField值在帖子后面保持不变。我选择的解决方案是使用ViewState保存值,然后在每个帖子上恢复我的动态控件。

- 编辑 -

感谢您的回复,因为我的问题可能有更好的解决方案,这里有一些代码可以显示我如何调用该方法以及我需要的原因。

    public void resetTitlePanel()
    {
        // Restylize the panel to initial state
        TitlePanel.Controls.Clear();
        TitlePanel.BorderColor = System.Drawing.Color.Maroon;
        TitlePanel.BorderStyle = BorderStyle.Dashed;
        TitlePanel.Enabled = true;

        // Set the new control properties to initial state
        Label TitleLabel = new Label();
        TitleLabel.ID = "TitleLabel";

        TextBox TitleTxtBox = new TextBox();
        TitleTxtBox.ID = "TitleTxtBox";

        // Add the new controls to the container
        TitlePanel.Controls.Add(TitleLabel);
        TitlePanel.Controls.Add(TitleTxtBox);

        // Set the reference of this to the new dynamic control
        this.TitleLabel = TitleLabel;
        this.TitleTxtBox = TitleTxtBox;
    }

    public void resetImagePanel()
    {
        // Restylize the panel to initial state
        ImagePanel.Controls.Clear();
        ImagePanel.BorderColor = System.Drawing.Color.Blue;
        ImagePanel.BorderStyle = BorderStyle.Dashed;
        ImagePanel.HorizontalAlign = HorizontalAlign.NotSet;

        // Set the new control properties to initial state
        Image AddImage = new Image();
        AddImage.ImageUrl = "~/Resources/Icons/picture_add.png";
        AddImage.ID = "AddImage";

        HiddenField HiddenImage = new HiddenField();
        HiddenImage.ID = "HiddenImage";

        // Add the new controls to the container
        ImagePanel.Controls.Add(AddImage);
        ImagePanel.Controls.Add(HiddenImage);

        // Set the reference of this to the new dynamic control
        this.AddImage = AddImage;
        this.HiddenImage = HiddenImage;
    }

通话方式:

private void copyFromSlide(TemplateControl destination, Template source)
    {
        // Reset the template
        destination.resetTitlePanel();
        destination.resetImagePanel();

        destination.Title = source.Title;
        // Find the path from the database and assign it to the control
        destination.ImagePath = modData.getImagePath((int)source.ImageID);
    }

所以...我明白代码很复杂,可能比它应该更多。此外,我只是一个初学者,所以质量可能更差,我为此道歉。

主要提示是:

  • 有2个用户控件互相交互。
  • 这完全没问题!IsPostback。
  • 默认情况下,ViewStateEnable为true,即使我明确指定为true,也会得到相同的结果。
  • 这完全适用于由标签和文本框组成的标题面板,两者都保留其值。
  • 我知道我将静态和动态控件混合在一起。我习惯了C,所以我不确定是否可以将对象指针移动到新的动态对象。

问题是,在分配图像路径时,该值不会保留在回发上。

我需要删除并重新添加控件,因为在特定条件下,我将删除控件并添加标签,如上所述,没有问题。我之所以认为我不需要再次初始化控件,是因为我正在添加到一个有根的面板,如下所示:

http://weblogs.asp.net/infinitiesloop/archive/2006/08/30/TRULY-Understanding-Dynamic-Controls-_2800_Part-3_2900_.aspx

我希望这会增加一些清晰度。

再次感谢,

-Brian

3 个答案:

答案 0 :(得分:1)

您是否在这些控件上启用了ViewState?

本文档的备注部分中有一些内容您可能需要查看here

答案 1 :(得分:1)

在InitComplete事件触发之前,ViewState不会跟踪更改。如果您在此之前进行更改并将它们存储在ViewState中(例如在Init中),则这些更改将不会生成新的视图状态键。 Init应该用于从viewstate重建您的控件。 Init事件之后的事件是您应该在视图状态中为这些控件设置新值,以便它们将被保留。

回答第二个问题:Image和HiddenField控件不响应任何事件(例如点击事件),因此不需要重建。这就是为什么你看到TextBox和Label控件与Image和HiddenField控件之间的不同行为。

可能更容易存储确定何时在页面视图状态中添加和删除这些控件的数据,并且只需在每个页面加载时重新创建控件。

答案 2 :(得分:0)

您需要做的是在OnLoad()发生之前(通常在OnInit()上)始终将所有控件添加到页面(或用户控件)中。

这是因为ASP.NET在OnLoad()上从ViewState或Request.Form加载控件值。

事实上,在回发之间没有任何“控件”被持久化,它只是在ViewState或Request.Form中回发之间保留的控件值。 (如果它们是以标记或动态方式添加的),如上所述,唯一重要的是控件在OnLoad()之前添加到页面中。

即使你在OnLoad之后添加元素,我也应该添加你仍然可以读取控件的值(在回发中),如下所示:

Request.Form[txtName.UniqueID]

有关ASP.NET中控件生命周期的更多信息,请参阅此处;

http://msdn.microsoft.com/en-us/library/ms178472.aspx