[英]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?
我应该怎么做才能达到我想要的?
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
...时,我开始感到后悔。
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.