具有动态下拉列表列的动态GridView中的动态ItemTemplate

3
我正在尝试在asp.net网格视图中创建动态列,并在这些动态列中插入动态下拉列表。最终结果应该类似于此:enter image description here请注意网格的右上方,其中有HSE1、HSE2等。这些列的含义将发生变化,在上面的示例中,我可能会有额外的HSE8、HSE9等。基本上,这些列是动态的。为了实现这一点,我已经完成了以下操作,这是我的网格视图的asp.net标记:
 <asp:GridView ID="gvMain" runat="server"
    AutoGenerateColumns="False"
    Width="100%" DataKeyNames="AreaLevelCostCenterFunctionID" OnPreRender="gvMain_PreRender" >
    <Columns>
        <asp:TemplateField HeaderText="JobTitle" >
            <ItemTemplate>
                <asp:HyperLink CssClass="loaderLink" ID="hlAreaLevel" runat="server" NavigateUrl='<%# "/Views/Training/AreaLevel/Details.aspx?AreaLevelID=" + 
                    Eval("AreaLevelCostCenter.AreaLevelID") %>' Text='<%# Eval( "AreaLevelCostCenter.AreaLevel.AreaLevel1" )%>' ToolTip="Area Level">
                </asp:HyperLink>
            </ItemTemplate>
            <ItemStyle HorizontalAlign="Left"></ItemStyle>
            <HeaderStyle HorizontalAlign="Left"></HeaderStyle>
        </asp:TemplateField>

        <!--HERE'S WHERE I ADD MY DYNAMIC COLUMNS -->
    </Columns>
    <PagerSettings Position="TopAndBottom" />
</asp:GridView>

为了填充这个网格视图(绑定它),我使用以下方法:
private void SetGvMainGridData(IEnumerable<AreaLevel> newNameList)
{
    if (newNameList != null)
    {
        BuildGridAdditionalColumns();
        gvMain.DataSource = newNameList;
        gvMain.DataBind();
        upData.Update();
    }
}

我的问题是,每当我分页数据或者回传筛选数据时,列数都会重复。这导致每次都会重新创建相同的列。因此,我编写了一些代码来解决这个问题,但我认为它看起来不太好。参数newNameList是HSE 1、HSE 2等课程的列表。下面是BuildGridAdditionalColumns的作用:

private void BuildGridAdditionalColumns()
{

   using (var db = DataCenterAccess.NewConnection())
    {
        var tManager = new TrainingManager(db, CurrentUser);
         //get the courses, THE HSE 1, HSE 2, etc...
        var preDefinedCourses = tManager.GetTrainingPredefinedCourses();
        if (preDefinedCourses != null && preDefinedCourses.Any())
        {
            foreach (var course in preDefinedCourses)
            {
                // Declare the template field
                TemplateField bfield = new TemplateField();
                //Initalize the DataField value.
                bfield.ItemTemplate = new GridViewTemplate(ListItemType.Item, course.TrainingPredefinedCourse1);
                //Initialize the HeaderText field value.
                bfield.HeaderText = course.TrainingPredefinedCourse1;

                //Add the newly created bound field to the GridView.
                gvMain.Columns.Add(bfield);
            }
        }
    }
}

请注意,我是如何执行 bfield.ItemTemplate = new GridViewTemplate(ListItemType.Item, course.TrainingPredefinedCourse1); 的。我必须创建一个接口来支持它,详细信息请参见此stackoverflow帖子:在代码后台中如何向GridView添加TemplateField?

基本上,这个接口看起来像这样:

 public class GridViewTemplate : ITemplate
    {
        //A variable to hold the type of ListItemType.
        readonly ListItemType _templateType;
        //A variable to hold the column name.
        readonly string _columnName;
        //Constructor where we define the template type and column name.

        public GridViewTemplate(ListItemType type, string colname)
        {
            //Stores the template type.
            _templateType = type;

            //Stores the column name.
            _columnName = colname;

        }

        void ITemplate.InstantiateIn(Control container)
        {
            if (_templateType == ListItemType.Item)
            {
                //Creates a new drop down list control.
                DropDownList ddl = new DropDownList {ID = _columnName}; 
                ddl.Attributes.Add("class","chosen-select");
                ddl.Width = 70;
                //get the data to populate ddl
                var tList = Utilities.GetCourseKeys().ToList();
                var selectedValues = (from t in tList select new ListItem( t.KeyValue, t.TrainingPredefinedCourseKeyID.ToString())).ToList();
                //add empty option to items and bind
                selectedValues.Insert(0, new ListItem());
                ddl.DataSource = selectedValues;
                ddl.DataBind();
                // ddl.DataBinding += new EventHandler(tb1_DataBinding);   //Attaches the data binding event.
                container.Controls.Add(ddl); //Adds the newly created ddl to the container.
            }
        }
    }

当我提交或刷新这些数据时,基本上会遇到两个问题。一个问题是列会重复出现。另一个问题是数据绑定停止工作(即x、y值变为空)。


BuildGridAdditionalColumns是做什么的? - JonH
我已经更新了这篇文章以便更好地阐明。 - MHendren
给你一个开放的悬赏以帮助提高一些可见度。 - JonH
2个回答

1
我认为你应该动态创建整个网格,请查看下面的代码。
                    string tempnum = "txtbox";
                    TemplateField temp1 = new TemplateField();
                    temp1.HeaderStyle.Width = Unit.Pixel(101);
                    temp1.HeaderStyle.CssClass = "headerwidth";
                    temp1.HeaderText = "txt";
                    temp1.ItemTemplate = new CreateTextBox(tempnum);
                    GridView1.Columns.Add(temp1);

1
在我的示例中,当您在Page_Init中创建动态模板字段并在Page_Load中进行GridView数据绑定时,它可以正常工作。我已经测试过了,如果有PostBack,就不会添加额外的列,所有的DropDownLists仍然存在,并且它们的所有数据和SelectedValues(如果在PostBack之前更改)都会正确显示。
protected void Page_Init(object sender, EventArgs e)
{
    //create a loop for the dynamic fields
    for (int i = 1; i < 6; i++)
    {
        //create a new template field
        TemplateField field = new TemplateField();
        field.HeaderText = "HSE " + i;

        //create the new itemtemplate
        field.ItemTemplate = new GridViewTemplate(DataControlRowType.DataRow, "HSE_" + i);

        //add the field to the grid 
        GridView1.Columns.Add(field);
    }
}

protected void Page_Load(object sender, EventArgs e)
{
    //normal use of IsPostBack
    if (!IsPostBack)
    {
        //bind the gridview data
        GridView1.DataSource = LoadFromDataBase();
        GridView1.DataBind();
    }
}

protected void Button1_Click(object sender, EventArgs e)
{
    Button1.Text = "PostBack is done!";
}

public class GridViewTemplate : ITemplate
{
    private DataControlRowType templateType;
    private string columnName;

    public GridViewTemplate(DataControlRowType type, string colname)
    {
        templateType = type;
        columnName = colname;
    }

    public void InstantiateIn(System.Web.UI.Control container)
    {
        switch (templateType)
        {
            case DataControlRowType.DataRow:
                DropDownList list = new DropDownList();
                list.DataSource = LoadFromDataBase();
                list.DataTextField = "myText";
                list.DataValueField = "myValue";
                list.DataBind();
                container.Controls.Add(list);
                break;

            default:
                break;
        }

    }
}

ASPX文件使得示例完整

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"></asp:GridView>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接