ID“itemPlaceholder”使用自定义 LayoutTemplate 时不会呈现
我创建了一个简单的 ASPX 页面,向该页面添加了一个 ListView 控件,并创建了 ITemplate 的两个实现;一种用于 LayoutTemplate,另一种用于 ItemTemplate。这里的技巧是,我指定要在 ListView 中显示的列的集合,并将该集合作为参数提供给我的 LayoutTemplate 类。这是整个代码(在“LoadDataSource”中调用“Columns.Skip(1)”只是为了验证我是否可以使用任意数量的列渲染 ListView):
public partial class ListViewITemplate : System.Web.UI.Page
{
private static IList<string> Columns
{
get
{
return new List<string>() { "ColumnA", "ColumnB", "ColumnC", "ColumnD", "ColumnE" };
}
}
protected void Page_Load(object sender, EventArgs e)
{
DataTable dataTable = LoadDataSource();
IEnumerable<string> columns = dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
MyListView.LayoutTemplate = new MyLayoutTemplate(columns);
MyListView.ItemTemplate = new MyItemTemplate(columns);
MyListView.DataSource = dataTable;
MyListView.DataBind();
}
private static DataTable LoadDataSource()
{
DataTable dataTable = new DataTable();
IEnumerable<string> selectedColumns = Columns.Skip(1);
foreach (string column in selectedColumns)
{
dataTable.Columns.Add(column, typeof(string));
}
for (int i = 0; i < 100; i++)
{
DataRow dataRow = dataTable.NewRow();
foreach (string column in selectedColumns)
{
dataRow[column] = "Data in " + column + " " + i;
}
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
}
public class MyLayoutTemplate : ITemplate
{
private IEnumerable<string> Columns { get; set; }
public MyLayoutTemplate(IEnumerable<string> columns)
{
Columns = columns;
}
public void InstantiateIn(Control container)
{
HtmlTable MyHtmlTable = new HtmlTable();
HtmlTableRow MyHtmlTableRow = new HtmlTableRow();
MyHtmlTableRow.Attributes["class"] = "tableheader";
foreach (string column in Columns)
{
HtmlTableCell MyHtmlTableCell = new HtmlTableCell();
LinkButton MyLinkButton = new LinkButton();
MyLinkButton.ID = "lbn" + column;
MyLinkButton.Text = column;
MyLinkButton.ToolTip = "Sort by " + column;
MyLinkButton.CommandArgument = column;
MyLinkButton.Command += new CommandEventHandler(MyLinkButton_Command);
MyHtmlTableCell.Controls.Add(MyLinkButton);
MyHtmlTableRow.Cells.Add(MyHtmlTableCell);
}
MyHtmlTable.Rows.Add(MyHtmlTableRow);
HtmlTableRow htmlTableRow = new HtmlTableRow();
htmlTableRow.ID = "itemPlaceholder";
MyHtmlTable.Rows.Add(htmlTableRow);
container.Controls.Add(MyHtmlTable);
}
void MyLinkButton_Command(object sender, CommandEventArgs e)
{
throw new NotImplementedException();
}
}
public class MyItemTemplate : ITemplate
{
private IEnumerable<string> Columns { get; set; }
public MyItemTemplate(IEnumerable<string> columns)
{
Columns = columns;
}
public void InstantiateIn(Control container)
{
HtmlTableRow MyHtmlTableRow = new HtmlTableRow();
foreach (string column in Columns)
{
HtmlTableCell MyHtmlTableCell = new HtmlTableCell();
MyHtmlTableCell.ID = "MyHtmlTableCell" + column;
Literal MyLiteral = new Literal();
MyLiteral.ID = "Data" + column;
MyHtmlTableCell.Controls.Add(MyLiteral);
MyHtmlTableRow.Cells.Add(MyHtmlTableCell);
}
MyHtmlTableRow.DataBinding += new EventHandler(MyTableRow_DataBinding);
container.Controls.Add(MyHtmlTableRow);
}
protected void MyTableRow_DataBinding(object sender, EventArgs e)
{
HtmlTableRow MyHtmlTableRow = (HtmlTableRow)sender;
DataRowView dataRowView = ((ListViewDataItem)MyHtmlTableRow.NamingContainer).DataItem as DataRowView;
foreach (string column in Columns)
{
HtmlTableCell MyHtmlTableCell = (HtmlTableCell)MyHtmlTableRow.FindControl("MyHtmlTableCell" + column);
Literal MyLiteral = (Literal)MyHtmlTableCell.FindControl("Data" + column);
MyLiteral.Text = dataRowView[column].ToString();
}
}
}
查看具有不同数量列的 ListView 没有问题,但每当我单击标题中的链接时,我都会收到此服务器错误而不是 MethodNotImplemented:
必须在 ListView“MyListView”上指定项目占位符...
我认为答案很简单,但我只是找不到原因。有人有什么建议吗?
I've created a simple ASPX-page, added a ListView control to the page and created two implementations of the ITemplate; one for the LayoutTemplate and one for the ItemTemplate. The trick here is that I specify a collection of columns I want to display in the ListView and supplying the collection as a parameter to my LayoutTemplate class. Here's the whole code (the call to "Columns.Skip(1)" in "LoadDataSource" is merely to verify that I can render the ListView with a arbitrary number of columns):
public partial class ListViewITemplate : System.Web.UI.Page
{
private static IList<string> Columns
{
get
{
return new List<string>() { "ColumnA", "ColumnB", "ColumnC", "ColumnD", "ColumnE" };
}
}
protected void Page_Load(object sender, EventArgs e)
{
DataTable dataTable = LoadDataSource();
IEnumerable<string> columns = dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
MyListView.LayoutTemplate = new MyLayoutTemplate(columns);
MyListView.ItemTemplate = new MyItemTemplate(columns);
MyListView.DataSource = dataTable;
MyListView.DataBind();
}
private static DataTable LoadDataSource()
{
DataTable dataTable = new DataTable();
IEnumerable<string> selectedColumns = Columns.Skip(1);
foreach (string column in selectedColumns)
{
dataTable.Columns.Add(column, typeof(string));
}
for (int i = 0; i < 100; i++)
{
DataRow dataRow = dataTable.NewRow();
foreach (string column in selectedColumns)
{
dataRow[column] = "Data in " + column + " " + i;
}
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
}
public class MyLayoutTemplate : ITemplate
{
private IEnumerable<string> Columns { get; set; }
public MyLayoutTemplate(IEnumerable<string> columns)
{
Columns = columns;
}
public void InstantiateIn(Control container)
{
HtmlTable MyHtmlTable = new HtmlTable();
HtmlTableRow MyHtmlTableRow = new HtmlTableRow();
MyHtmlTableRow.Attributes["class"] = "tableheader";
foreach (string column in Columns)
{
HtmlTableCell MyHtmlTableCell = new HtmlTableCell();
LinkButton MyLinkButton = new LinkButton();
MyLinkButton.ID = "lbn" + column;
MyLinkButton.Text = column;
MyLinkButton.ToolTip = "Sort by " + column;
MyLinkButton.CommandArgument = column;
MyLinkButton.Command += new CommandEventHandler(MyLinkButton_Command);
MyHtmlTableCell.Controls.Add(MyLinkButton);
MyHtmlTableRow.Cells.Add(MyHtmlTableCell);
}
MyHtmlTable.Rows.Add(MyHtmlTableRow);
HtmlTableRow htmlTableRow = new HtmlTableRow();
htmlTableRow.ID = "itemPlaceholder";
MyHtmlTable.Rows.Add(htmlTableRow);
container.Controls.Add(MyHtmlTable);
}
void MyLinkButton_Command(object sender, CommandEventArgs e)
{
throw new NotImplementedException();
}
}
public class MyItemTemplate : ITemplate
{
private IEnumerable<string> Columns { get; set; }
public MyItemTemplate(IEnumerable<string> columns)
{
Columns = columns;
}
public void InstantiateIn(Control container)
{
HtmlTableRow MyHtmlTableRow = new HtmlTableRow();
foreach (string column in Columns)
{
HtmlTableCell MyHtmlTableCell = new HtmlTableCell();
MyHtmlTableCell.ID = "MyHtmlTableCell" + column;
Literal MyLiteral = new Literal();
MyLiteral.ID = "Data" + column;
MyHtmlTableCell.Controls.Add(MyLiteral);
MyHtmlTableRow.Cells.Add(MyHtmlTableCell);
}
MyHtmlTableRow.DataBinding += new EventHandler(MyTableRow_DataBinding);
container.Controls.Add(MyHtmlTableRow);
}
protected void MyTableRow_DataBinding(object sender, EventArgs e)
{
HtmlTableRow MyHtmlTableRow = (HtmlTableRow)sender;
DataRowView dataRowView = ((ListViewDataItem)MyHtmlTableRow.NamingContainer).DataItem as DataRowView;
foreach (string column in Columns)
{
HtmlTableCell MyHtmlTableCell = (HtmlTableCell)MyHtmlTableRow.FindControl("MyHtmlTableCell" + column);
Literal MyLiteral = (Literal)MyHtmlTableCell.FindControl("Data" + column);
MyLiteral.Text = dataRowView[column].ToString();
}
}
}
I have no problem viewing the ListView with varying number of columns, but whenever I click the link in the header I get this server error instead of MethodNotImplemented:
An item placeholder must be specified on ListView 'MyListView'...
I think the answer is straightforward but I just can't find the cause of this. Does anyone have any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,我找到了发生这种情况的原因 - 下面添加了代码...
首先,在 MyItemTemplate->MyTableRow_DataBinding 中,我使用 FindControl 加载控件并为其赋值。这些控件已添加到 InstantiateIn 方法中。显然,这不是正确的方法。
相反,您需要在 DataBinding 事件中创建控件,分配正确的值并将它们添加到 MyHtmlTableRow(sender 参数)。
其次,我需要能够渲染更复杂的表格设计(包括 thead 和 tbody),因此我用 HtmlGenericControl 替换了 HtmlTable、HtmlTableRow 和 HtmlTableCell 的使用,并将标签名称作为参数传递,如下所示:
作为注释,您可能可以使用除 HtmlGenericControl 之外的其他服务器控件,例如 Table、TableHeaderRow、TableHeaderCell 等,也就是说,在这种情况下可能没有任何区别,但主要问题已解决。
Okay, I found out why this happened - code is added below...
First of all, in MyItemTemplate->MyTableRow_DataBinding I'm using FindControl to load the controls and assign values to them. These controls were already added in the InstantiateIn method. Apparently, that's not the right way.
Instead you need to create the controls in the DataBinding event, assign the correct values and add them to the MyHtmlTableRow (the sender parameter).
Secondly, I needed to be able to render a more complex table design (including thead and tbody) so I replaced the use of HtmlTable, HtmlTableRow and HtmlTableCell with HtmlGenericControl and passed the tag name as parameter, like so:
As a note you could probably use other server controls than HtmlGenericControl, e.g. Table, TableHeaderRow, TableHeaderCell etc., that is to say it probably didn't make any difference in this case but the main issue is solved.