我有一个转发器循环遍历不同类型的对象列表。我想根据类型不同地渲染对象。为此,我需要某种控制(因为我想避免使用代码隐藏),其行为类似于switch / case语句。基本上它看起来像这样:
<xxx:TestType Object='<%# Container.DataItem %>'>
<Case Type="Namespace.ClassX">
<asp:Label ... />
</Case>
<Case Type="Namespace.ClassY">
<asp:TextBox ... />
</Case>
<Default>
<p>Other</p>
</Default>
</xxx:TestType>
之前我做过网页控制,但这是一个相当复杂的...
<Case>
元素?<Case Type="...">
元素,还是仅限于无属性元素?我猜我必须为<Case>
元素创建一个类型,并以某种方式为主Web控件指定它?
我会感激任何指针,教程链接等等!
或者,建议基于当前绑定对象的类型呈现不同HTML / ASP.NET控件的更好方法。突然出现在我脑海中的第一种方法是我认为(非常)丑陋:
<asp:PlaceHolder Visible='<%# CheckType(Container, typeof(ClassX)) %>' runat="server">
...
</asp:PlaceHolder>
<asp:PlaceHolder Visible='<%# CheckType(Container, typeof(ClassY)) %>' runat="server">
...
</asp:PlaceHolder>
答案 0 :(得分:1)
MultiView控件是ASP.NET中与C#switch语句最接近的开箱即用。
答案 1 :(得分:1)
查看implementing ITemplate interface
public class Case
{
[PersistenceMode(PersistenceMode.Attribute)]
public string Type { get; set; }
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public ITemplate Template { get; set; }
}
public class DeclarativeCase
: CompositeControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public List<Case> Cases { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Default { get; set; }
}
<xxx:DeclarativeCase runat="server" ID="test">
<Cases>
<xxx:Case Type="Namespace.TypeName">
<Template>
<asp:Label ID="Label1" runat="server"></asp:Label>
</Template>
</xxx:Case>
</Cases>
<Default>
<asp:Label ID="Label2" runat="server"></asp:Label>
</Default>
</xxx:DeclarativeCase>
答案 2 :(得分:0)
为什么不丢弃服务器控件并使用C#switch语句。您只需将其包装在代码标记中即可。
另一种方法是迭代(for循环)。使用type属性和render方法创建一个接口。然后迭代接口,直到找到正确的类型。
答案 3 :(得分:0)
前一段时间我有类似的要求,我做了类似的事情:
[ParseChildren(true, "Templates")]
public class TypedRepeater : CompositeDataBoundControl
{
[
PersistenceMode(PersistenceMode.InnerProperty),
Browsable(false),
MergableProperty(false)
]
public TypedTemplateCollection Templates
{
get;
}
protected TypedTemplate GetTemplate(object dataItem) { if(dataItem == null) { return null; } foreach(模板中的TypedTemplate模板) { 输入itemType = dataItem.GetType(); if(dataItem.IsAssignableFrom(template.Type)) { 返回模板; } } return null; }
protected TypedTemplateRepeaterItem CreateItem(int index, object dataItem, bool dataBinding)
{
TypedTemplateRepeaterItem repeaterItem = new TypedTemplateRepeaterItem();
if ((!dataBinding) && (ViewState[string.Format("TemplateIxc_{0}", index)] is int))
{
int _template = (int)ViewState[string.Format("TemplateIxc_{0}", index)];
if ((_template >= 0) && (_template < Templates.Count) && (Templates[_template].ItemTemplate != null))
{
Templates[_template].ItemTemplate.InstantiateIn(repeaterItem);
}
else
{
DefaultTemplate.InstantiateIn(repeaterItem);
}
}
else if (dataBinding)
{
TypedTemplate template = GetTemplate(dataItem);
ITemplate itemTemplate = DefaultTemplate;
if (template != null)
{
itemTemplate = template.ItemTemplate;
ViewState[string.Format("TemplateIxc_{0}", index)] = Templates.IndexOf(template);
}
else
{
ViewState[string.Format("TemplateIxc_{0}", index)] = -1;
}
repeaterItem.DataItem = dataItem;
repeaterItem.DataItemIndex =
repeaterItem.DisplayIndex = index;
itemTemplate.InstantiateIn(repeaterItem);
repeaterItem.DataBind();
repeaterItem.DataItem = null;
}
return repeaterItem;
}
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
int count = 0;
if (dataSource != null)
{
foreach (object dataItem in dataSource)
{
TypedTemplateRepeaterItem repeaterItem = CreateItem(count, dataItem, dataBinding);
Controls.Add(repeaterItem);
count++;
}
}
return count;
}
}
其中TypedTemplateCollection是TypedTemplate类的StateManagedCollection:
[ParseChildren(true, "ItemTemplate")]
public class TypedTemplate
{
public Type Type
{
get { return Type.GetType(TypeName); }
}
[
PersistenceMode(PersistenceMode.Attribute),
Browsable(true),
DefaultValue("")
]
public string TypeName
{
get;
set;
}
[
PersistenceMode(PersistenceMode.InnerProperty),
Browsable(true),
DefaultValue(typeof(ITemplate), null),
TemplateContainer(typeof(TypedTemplateRepeaterItem))
]
public ITemplate ItemTemplate
{
get;
set;
}
}
和TypedTemplateRepeaterItem是:
public class TypedTemplateRepeaterItem : WebControl, INamingContainer, IDataItemContainer
{
#region IDataItemContainer Members
public object DataItem
{
get;
set;
}
public int DataItemIndex
{
get;
set;
}
public int DisplayIndex
{
get;
set;
}
#endregion
}
答案 4 :(得分:0)
MSDN网站有一个简单明确的模板示例,看起来似乎就像你的情况一样。