简体   繁体   English

绑定自定义控件时如何按一定顺序放置子控件?

[英]How to place child controls in a certain order when binding a custom control?

What I'm trying to achieve is a custom calendar where I place events. 我想要实现的是一个自定义日历,用于放置事件。

I've created a basic custom control which simply lists the events: 我创建了一个基本的自定义控件,该控件仅列出事件:

namespace MyControls
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;

    public class Calendar : CompositeDataBoundControl
    {
        protected override Int32 CreateChildControls(IEnumerable dataSource, Boolean dataBinding)
        {
            Int32 itemCounter = 0;

            if (dataSource != null)
            {
                IEnumerator dataSourceEnumerator = dataSource.GetEnumerator();

                while (dataSourceEnumerator.MoveNext())
                {
                    LinkButton eventLink = new LinkButton();

                    eventLink.Click += new EventHandler(EventLinkClick);

                    HtmlGenericControl eventContainer = new HtmlGenericControl();

                    eventContainer.Controls.Add(eventLink);
                    eventContainer.TagName = "p";

                    this.Controls.Add(eventContainer);

                    if (dataBinding)
                    {
                        CalendarEvent currentEvent = (CalendarEvent) dataSourceEnumerator.Current;

                        eventLink.CommandArgument = String.Concat(currentEvent.Name, "§", currentEvent.Day.ToBinary());
                        eventLink.Text = currentEvent.Name;
                        eventLink.ToolTip = currentEvent.Description;
                    }

                    itemCounter++;
                }
            }

            return itemCounter;
        }

        protected void EventLinkClick(Object sender, EventArgs e)
        {
        }
    }
}

The control works, when I pass it a List<CalendarEvent> it displays every event's LinkButton inside its own <p /> , when I click a LinkButton the EventLinkClick method gets called, and after the postback the LinkButton s are still there with their values. 该控件起作用,当我将其传递给List<CalendarEvent>它将在其自己的<p />显示每个事件的LinkButton ,当我单击LinkButton ,将调用EventLinkClick方法,并且在回发之后, LinkButton仍带有它们的值。

However, I don't need a plain list of the event, I need to place my events inside a calendar, inside the correct day. 但是,我不需要事件的明细清单,我需要将事件放在正确日期的日历中。

I create my calendar like this: 我这样创建日历:

Int32 year = 2011;

Table monthTable = null;

TableRow weekRow = null;

for (DateTime day = new DateTime(year, 1, 1); day.Year == year; day = day.AddDays(1))
{
    if (day.Day == 1)
    {
        HtmlGenericControl monthName = new HtmlGenericControl();

        monthName.InnerText = CultureInfo.CurrentUICulture.DateTimeFormat.GetMonthName(day.Month);
        monthName.TagName = "h2";

        this.Controls.Add(monthName);

        monthTable = new Table();

        TableHeaderRow headerRow = new TableHeaderRow();

        headerRow.TableSection = TableRowSection.TableHeader;

        monthTable.Rows.Add(headerRow);

        for (Int32 i = 0; i < 7; i++)
        {
            TableHeaderCell dayOfWeekCell = new TableHeaderCell();

            dayOfWeekCell.Text = CultureInfo.CurrentUICulture.DateTimeFormat.GetShortestDayName((DayOfWeek) i);

            headerRow.Cells.Add(dayOfWeekCell);
        }

        weekRow = new TableRow();

        weekRow.TableSection = TableRowSection.TableBody;

        for (Int32 i = 0; i < (Int32) day.DayOfWeek; i++)
        {
            weekRow.Cells.Add(new TableCell());
        }
    }

    if (day.DayOfWeek == DayOfWeek.Sunday && day.Day != 1)
    {
        monthTable.Rows.Add(weekRow);

        weekRow = new TableRow();

        weekRow.TableSection = TableRowSection.TableBody;
    }

    TableCell dayCell = new TableCell();

    dayCell.Text = Convert.ToString(day.Day);

    weekRow.Cells.Add(dayCell);

    if (day.Day == DateTime.DaysInMonth(day.Year, day.Month))
    {
        for (Int32 i = (Int32) day.DayOfWeek; i < 6; i++)
        {
            weekRow.Cells.Add(new TableCell());
        }

        monthTable.Rows.Add(weekRow);

        this.Controls.Add(monthTable);
    }
}

which yields to something like this: 产生这样的东西:

我的日历示例 .

Now, how can I integrate the two things? 现在,我该如何整合这两件事?

What I came up with is casting the dataSource parameter to IEnumerable<CalendarEvents> and after the dayCell.Text = Convert.ToString(day.Day); dayCell.Text = Convert.ToString(day.Day);是将dataSource参数转换为IEnumerable<CalendarEvents>并在dayCell.Text = Convert.ToString(day.Day); line I get the events of the day from the IEnumerable<CalendarEvents> through LINQ. 我通过LINQ从IEnumerable<CalendarEvents>获取当天的事件。

However, this breaks on postback because when the control is recreating itself after a postback the dataSource parameter is full of nulls, so I can't fetch the events of the day, so I can't recreate the controls. 但是,这在回发时会中断,因为在回发后控件重新创建自身时, dataSource参数充满了null,因此我无法获取当天的事件,因此无法重新创建控件。

I couldn't find anything on the net about this, and I'm completely stuck. 我在网上找不到任何关于此的信息,而且我完全陷入了困境。

Am I missing (or messing) something? 我是否想念(或弄乱)某些东西? What should I do to achieve what I'm looking for? 我应该怎么做才能达到我想要的?

Update #1 更新#1

As StriplingWarrior suggested I tried to save the dataSource in the ViewState, however I failed dramatically. 正如StriplingWarrior所建议的那样,我试图将dataSource保存在ViewState中,但是我失败了。

What I tried is this: at the beginning of the CreateChildControls method I placed 我尝试的是:在放置的CreateChildControls方法的开头

if (dataBinding)
{
    this.ViewState.Add("myDataSource", dataSource);
}

IEnumerable myDataSource = (IEnumerable) this.ViewState["myDataSource"];

and replaced every call to dataSource with myDataSource . 并用myDataSource替换对dataSource每次调用。

However, when the page post backs this.ViewState["myDataSource"] is null , and I'm back to square one. 但是,当页面帖子支持this.ViewState["myDataSource"]null ,我回到第一位。

I'm starting to regret when I decided to go with a CompositeDataBoundControl ... :\\ 当我决定使用CompositeDataBoundControl ...时,我开始感到后悔。

Update #2 更新#2

I tried to create a new project containing only the custom control, and I rewrote it from scratch, and StriplingWarrior's suggestion worked: 我试图创建一个仅包含自定义控件的新项目,并从头开始重写了它, StriplingWarrior的建议起作用了:

if (dataBinding)
{
    this.ViewState.Add("DataSource", dataSource);
}
else
{
    dataSource = (IEnumerable) this.ViewState["DataSource"];
}

However, I haven't been able to pinpoit what was causing the this.ViewState["DataSource"] in the original solution. 但是,我无法确定导致原始解决方案中this.ViewState["DataSource"]的原因。

You're running into ViewState issues. 您遇到了ViewState问题。 You can either disable viewstate on your control, or write the control in such a way that it saves the information it needs in ViewState, so it doesn't need to rebind to the data source on subsequent postbacks. 您可以在控件上禁用viewstate,或以将控件所需的信息保存在ViewState中的方式编写控件,因此在以后的回发中不需要将其重新绑定到数据源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM