我有一组生成的自定义控件,扩展为CompositeControl
,定义为:
[PersistChildren(true)]
[ToolboxData("<{0}:ContractControl runat=server></{0}:ContractControl>")]
public class ContractControl : CompositeControl
{
private int contractID = 0;
private ContractTileControl tileControl = null;
private ContractDetailControl detailControl = null;
private HtmlGenericControl contractMainDiv = null;
public int ContractID
{
get { return this.contractID; }
set { this.contractID = value; }
}
public ContractTileControl TileControl
{
get { return this.tileControl; }
set { this.tileControl = value; }
}
public ContractDetailControl DetailControl
{
get { return this.detailControl; }
set { this.detailControl = value; }
}
public ContractControl()
{
this.contractMainDiv = new HtmlGenericControl("div");
this.contractMainDiv.ID = "contractMainDiv";
this.contractMainDiv.Attributes.Add("class", "contractMain");
}
#region protected override void OnPreRender(EventArgs e)
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//CreateChildControls();
}
#endregion
#region protected override void CreateChildControls()
protected override void CreateChildControls()
{
base.CreateChildControls();
if (tileControl != null)
{
this.contractMainDiv.Controls.Add(tileControl);
}
if (detailControl != null)
{
this.contractMainDiv.Controls.Add(detailControl);
}
this.Controls.Add(contractMainDiv);
//base.CreateChildControls();
}
#endregion
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
CreateChildControls();
}
protected override void OnInit(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
}
}
其中ContractTileControl
和ContractDetailControl
是从CompositeControl
派生的另一个自定义控件。
当我将它们添加到asp:PlaceHolder
控件集时,它们渲染得很好,但是当我定义一个转发器时:
<asp:Repeater ID="myRepeater" runat="server" >
<HeaderTemplate>
<table border="0" cellpadding="0" cellspacing="0">
</HeaderTemplate>
<ItemTemplate>
<tr><td><easit:ContractControl ID="contractControl" runat="server" />
</td></tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
并将它们绑定到它:
private void FillContractPlaceHolder()
{
List<ContractControl> controls = new List<ContractControl>();
foreach(KeyValuePair<Customer, List<TFSContract>> pair in contractList)
{
Label customerNameLbl = new Label();
customerNameLbl.ID = "customerNameLbl";
customerNameLbl.CssClass = "customerName";
customerNameLbl.Text = pair.Key.Name;
contractListPlaceHolder.Controls.Add(customerNameLbl);
foreach (TFSContract contract in pair.Value)
{
ContractStatusBarControl status = new ContractStatusBarControl();
status.WidthPercent = GetFillPercent(contract.NumberOfTasks, contract.NumberOfFinishedTasks);
string[] contractNameParts = Regex.Split(contract.Contract.Name, @"[A-Z]{3}-[0-9|A-Z]{2}-[0-9|A-Z]{2}", RegexOptions.IgnoreCase);
ContractDetailControl detail = new ContractDetailControl();
detail.ContractName = contractNameParts.Last();
detail.DateStarted = contract.StartDate;
detail.DateFinished = contract.FinishDate;
detail.StatusBar = status;
ContractTileControl tile = new ContractTileControl();
Match match = Regex.Match(contract.Contract.Name, @"[A-Z]{3}-[0-9|A-Z]{2}-[0-9|A-Z]{2}", RegexOptions.IgnoreCase);
if (match.Value.Length != 0)
{
tile.ContractNumber = match.Value;
}
tile.ContractTasksFinished = contract.NumberOfFinishedTasks;
tile.ContractTasksTotal = contract.NumberOfTasks;
ContractControl contractControl = new ContractControl();
contractControl.ContractID = contract.Contract.Id;
contractControl.TileControl = tile;
contractControl.DetailControl = detail;
//contractListPlaceHolder.Controls.Add(contractControl);
controls.Add(contractControl);
}
}
myRepeater.DataSource = controls;
myRepeater.DataBind();
}
表已创建,但只有contractMainDiv
的非复合部分ContractControl
会被呈现,因为Repeater坚持tileControl
和detailControl
都为空,甚至虽然它们已正确设置为各自类型的实例。
答案 0 :(得分:2)
当Repeater
受数据限制时,它会为数据源中的每个项目创建ItemTemplate
的实例,并将其DataItem
设置为数据源中的项目和数据绑定孩子们。
在这种情况下,数据源中的项目是ContractControl
的实例,而您的ItemTemplate
没有数据绑定,因此您最终会得到一个空白的实例您已添加到列表中的每个项目ContractControl
。
快速而肮脏的解决方案是为ItemDataBound
的{{1}}事件添加处理程序,并将属性复制到实际控件:
Repeater
更好的解决方案是将protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
switch (e.Item.ItemType)
{
case ListItemType.Item:
case ListItemType.AlternatingItem:
case ListItemType.SelectedItem:
case ListItemType.EditItem:
{
var source = (ContractControl)e.Item.DataItem;
var destination = (ContractControl)e.Item.FindControl("contractControl");
destination.ContractID = source.ContractID;
destination.TileControl = source.TileControl;
destination.DetailControl = source.DetailControl;
break;
}
}
}
绑定到Repeater
个对象列表,然后移动代码以将TFSContract
构建到ContractControl
事件处理程序中。< / p>
修改强>
更新为仅处理实际项目,忽略页眉,页脚等。