C# 如何在数据绑定转发器中创建条件内容
我正在设置一个由XML配置驱动的用户控件。用例子来解释比较容易。请查看以下配置代码段:C# 如何在数据绑定转发器中创建条件内容,c#,asp.net,dynamic,user-controls,repeater,C#,Asp.net,Dynamic,User Controls,Repeater,我正在设置一个由XML配置驱动的用户控件。用例子来解释比较容易。请查看以下配置代码段: <node> <text lbl="Text:"/> <checkbox lbl="Check me:" checked="true"/> </node> 我试图实现的是将该代码片段转换为单个文本框和复选框控件。当然,如果代码段包含更多节点,则会自动生成更多控件 鉴于任务的迭代性质,我选择使用Repeater。在其中,我放置了两个(更多,请参见下面
<node>
<text lbl="Text:"/>
<checkbox lbl="Check me:" checked="true"/>
</node>
我试图实现的是将该代码片段转换为单个文本框和复选框控件。当然,如果代码段包含更多节点,则会自动生成更多控件
鉴于任务的迭代性质,我选择使用Repeater。在其中,我放置了两个(更多,请参见下面的)控件,一个复选框和一个编辑框。为了选择激活哪个控件,我使用了一个内联开关命令,检查当前配置节点的名称
遗憾的是,这不起作用。问题在于,该开关是在数据绑定发生很久之后的渲染期间运行的。这本身并不是问题,因为配置节点可能会向数据绑定提供所需的信息。考虑一下,如果复选框控件将尝试绑定到上面的代码段中的文本节点,就会拼命寻找它的“选中”属性。
有什么办法可以做到这一点吗
谢谢,
波阿斯
这是我目前的代码:
下面是我的代码(它的语法比上面的更复杂):
您需要看起来更像这样的东西:
<ItemTemplate>
<%# GetContent(Page.GetDataItem()) %>
</ItemTemplate>
然后在代码中生成所有控件 一个周末后,以下是我带来的解决方案。我的主要目标是找到既能工作又能让您在标记中不断指定项模板的确切内容的东西。从代码中执行操作可能会起作用,但仍然会很麻烦 代码应该是直截了当的,但要点在于两个部分 第一个是使用Repeater item created事件过滤掉模板中不需要的部分 第二种方法是存储在ViewState中做出的决策,以便在回发期间重新创建页面。后面的内容非常重要,因为您会注意到我使用了Item.DataItem。在回发期间,控件的重新创建在页面生命周期中发生得更早。触发ItemCreate时,DataItem为null 以下是我的解决方案: 控件标记
<asp:Repeater ID="settingRepeater" runat="server"
onitemcreated="settingRepeater_ItemCreated"
>
<ItemTemplate>
<asp:PlaceHolder ID="text" runat="server">
<asp:Label ID="settingsLabel" CssClass="editlabel" Text='<%# XPath("@lbl") %>' runat="server" />
<asp:TextBox ID="settingsLabelText" runat="server"
Text='<%# SettingsNode.SelectSingleNode(XPath("@xpath").ToString()).InnerText %>'
Columns='<%# XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"@width",20) %>'
/>
</asp:PlaceHolder>
<asp:PlaceHolder ID="att_adder" runat="server">
<asp:CheckBox ID="settingsAttAdder" Text='<%# XPath("@lbl") %>' runat="server"
Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("@xpath").ToString())).HasAttribute(XPath("@att").ToString()) %>'
/>
</asp:PlaceHolder>
</ItemTemplate>
</asp:Repeater>
注意:为了更加方便,我添加了占位符控件来分组,并使删除哪些控件的决定更加容易
代码隐藏
下面的代码建立在每个中继器项都是一种类型的概念之上。该类型是从配置xml中提取的。在我的特定场景中,我可以通过ID将该类型设置为单个控件。如果需要,可以轻松修改该类型
protected List<string> repeaterItemTypes
{
get
{
List<string> ret = (List<string>)ViewState["repeaterItemTypes"];
if (ret == null)
{
ret = new List<string>();
ViewState["repeaterItemTypes"] = ret;
}
return ret;
}
}
protected void settingRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
string type;
if (e.Item.DataItem != null)
{
// data binding mode..
type = ((XmlNode)e.Item.DataItem).LocalName;
int i = e.Item.ItemIndex;
if (i == repeaterItemTypes.Count)
repeaterItemTypes.Add(type);
else
repeaterItemTypes.Insert(e.Item.ItemIndex, type);
}
else
{
// restoring from ViewState
type = repeaterItemTypes[e.Item.ItemIndex];
}
for (int i = e.Item.Controls.Count - 1; i >= 0; i--)
{
if (e.Item.Controls[i].ID != type) e.Item.Controls.RemoveAt(i);
}
}
受保护的列表重复项类型
{
得到
{
List ret=(List)ViewState[“repeaterItemTypes”];
if(ret==null)
{
ret=新列表();
ViewState[“repeaterItemTypes”]=ret;
}
返回ret;
}
}
已创建受保护的无效设置Repeater_项(对象发送方,RepeaterItemEventArgs e)
{
字符串类型;
如果(e.Item.DataItem!=null)
{
//数据绑定模式。。
type=((XmlNode)e.Item.DataItem).LocalName;
int i=e.Item.ItemIndex;
if(i==repeaterItemTypes.Count)
repeaterItemTypes.Add(类型);
其他的
repeaterItemTypes.Insert(例如Item.ItemIndex,type);
}
其他的
{
//从ViewState还原
type=repeaterItemTypes[e.Item.ItemIndex];
}
对于(int i=e.Item.Controls.Count-1;i>=0;i--)
{
如果(e.Item.Controls[i].ID!=type)e.Item.Controls.RemoveAt(i);
}
}
protected List<string> repeaterItemTypes
{
get
{
List<string> ret = (List<string>)ViewState["repeaterItemTypes"];
if (ret == null)
{
ret = new List<string>();
ViewState["repeaterItemTypes"] = ret;
}
return ret;
}
}
protected void settingRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
string type;
if (e.Item.DataItem != null)
{
// data binding mode..
type = ((XmlNode)e.Item.DataItem).LocalName;
int i = e.Item.ItemIndex;
if (i == repeaterItemTypes.Count)
repeaterItemTypes.Add(type);
else
repeaterItemTypes.Insert(e.Item.ItemIndex, type);
}
else
{
// restoring from ViewState
type = repeaterItemTypes[e.Item.ItemIndex];
}
for (int i = e.Item.Controls.Count - 1; i >= 0; i--)
{
if (e.Item.Controls[i].ID != type) e.Item.Controls.RemoveAt(i);
}
}