ASP.NET向导中的动态UserControl

时间:2014-04-23 15:47:32

标签: c# asp.net .net dynamic wizard

我试图让网页用户(ASP.NET WebForms)在WizardStep中添加动态的用户控件列表。我从没想过会有这么困难,但我不知道该如何做到这一点。我的最终目标是让用户在WizardStep中添加用户控件,并且如果用户转到不同的WizardStep(也就是向导进度),那么数据就会一直存在。我发现很难能够动态添加用户控件,而且如果用户离开此向导步骤,我也不知道如何保持用户控制。请帮忙!

2 个答案:

答案 0 :(得分:2)

我没有动态创建UserControl,而是提出了一种涉及Repeater的方法。该方法还允许用户添加未知数量的项目,但避免了动态创建的控件的复杂性。为了实现真正动态的方法,您需要在每次回发的早期重新创建控件。如果不这样做,迟早会遇到麻烦,因为事件不会按预期触发,或者您无法检索用户已更改的数据。

因此,以下方法可避免动态创建控件,但使用Repeater显示UserControls。我选择了一个Repeater,以便在呈现的HTML方面保持灵活性。

根据您的评论,我创建了一个简单的 UserControl ,其中包含两个文本框:

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="MyUserControl.ascx.cs" 
    Inherits="TestWizard.MyUserControl" %>
<table>
    <tr>
        <td>
            <asp:TextBox ID="txt1" runat="server" />
        </td>
        <td>
            <asp:TextBox ID="txt2" runat="server" />
        </td>
    </tr>
</table>

在UserControl的代码隐藏文件中,我定义了一个类,其中包含UserControl中使用的数据以及可用于获取和设置数据的属性:

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

namespace TestWizard
{
    public class MyUserControlData
    {
        public string Text1 { get; set; }
        public string Text2 { get; set; }
    }

    public partial class MyUserControl : System.Web.UI.UserControl
    {
        public MyUserControlData Data
        {
            get
            {
                return new MyUserControlData() 
                       { Text1 = txt1.Text, Text2 = txt2.Text };
            }
            set
            {
                txt1.Text = value.Text1;
                txt2.Text = value.Text2;
            }
        }
    }
}

我创建了一个页面,其中包含一个向导控件,包含3个步骤。第一个和最后一个是没用的,但第二步包含一个添加新项的按钮和一个在ItemTemplate中托管UserControl实例的Repeater。用于获取和设置数据的UserControl的属性绑定到RepeaterItem的DataItem。

<asp:Wizard ID="wiz" runat="server" 
            OnFinishButtonClick="wiz_FinishButtonClick">
    <WizardSteps>
        <asp:WizardStep runat="server">
            <asp:Literal runat="server" Text="First Wizard Page" />
        </asp:WizardStep>
        <asp:WizardStep runat="server">
            <asp:Button ID="btnAddNewEntry" runat="server" 
                        Text="Add New Entry" 
                        OnClick="btnAddNewEntry_Click" />
            <asp:Repeater ID="rpt" runat="server">
                <ItemTemplate>
                    <uc:MyUserCtrl ID="myUserCtrl" runat="server" 
                         Data='<%# Container.DataItem %>' />
                </ItemTemplate>
            </asp:Repeater>
        </asp:WizardStep>
        <asp:WizardStep runat="server">
            <asp:Literal runat="server" Text="Last Wizard Page" />
        </asp:WizardStep>
    </WizardSteps>
</asp:Wizard>    

页面代码隐藏文件中一个非常重要的方法是从Repeater 检索数据的方法。它基本上迭代了Repeater的行,并在列表中收集Data属性。

private List<MyUserControlData> GetUserControlData()
{
    var lst = new List<MyUserControlData>();
    foreach(RepeaterItem item in rpt.Items)
    {
        var uc = item.FindControl("myUserCtrl") as MyUserControl;
        if (uc != null)
            lst.Add(uc.Data);
    }
    return lst;
}

此方法用于各种场合:首先,当向Repeater添加新项时,将检索现有内容并将新项添加到列表中:

protected void btnAddNewEntry_Click(object sender, EventArgs e)
{
    var data = GetUserControlData();
    var newData = new MyUserControlData() 
                      { Text1 = "New Item", 
                        Text2 = "Created at " + DateTime.Now.ToString() };
    data.Add(newData);
    rpt.DataSource = data;
    rpt.DataBind();
}

此外,当完成向导时,您可以通过以下方式检索数据:

protected void wiz_FinishButtonClick(object sender, WizardNavigationEventArgs e)
{
    var data = GetUserControlData();
    // Do something with the data
}

示例按预期工作,很容易检索用户输入文本框的数据。如果您有任何问题,请在评论中告诉我。

答案 1 :(得分:0)

这样做的方法是创建一个自定义类,如下所示:

public class WizardControl
{
    public System.Web.UI.Control Control { get; set; }
    public int WizardStep { get; set; }
}

然后在你的页面加载,创建(或加载)对象列表,如下所示:

if (_wizardControls==null)
{
    if (ViewState["WizardControls"] == null)
        _wizardControls = new List<WizardControl>();
    else _wizardControls = (List<WizardControl>)ViewState["WizardControls"];
 }

最后,在向导页面上,当用户选择控件时,请创建此类的实例:

var control = new WizardControl();
control.Control = _userSelectedControl;  // Add whatever control the user selected
control.WizardStep = _wizardStep; // Set to whatever wizard page this control belongs to.
_wizardControls.Add(control); // Add it to our collection
ViewState["WizardControls"] = _wizardControls; // Save it into the ViewState