1

我有一个中继器循环遍历不同类型的对象列表。我想根据对象的类型以不同的方式渲染对象。为此,我需要某种行为类似于 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>
4

5 回答 5

1

MultiView控件是 ASP.NET 中最接近 C# switch 语句的现成控件。

于 2009-09-21T09:27:02.413 回答
1

看看实现 ITemplate 接口

  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>
于 2009-09-21T09:47:39.457 回答
0

为什么不放弃服务器控制并使用 C# switch 语句。您只需将其包装在代码标签中即可。

另一种方法是迭代(for循环)。创建具有类型属性和渲染方法的接口。然后遍历接口,直到找到正确的类型。

于 2009-09-21T09:06:10.473 回答
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(Templates 中的 TypedTemplate 模板){ Type itemType = dataItem.GetType(); if (dataItem.IsAssignableFrom(template.Type)) { 返回模板;} } 返回空值;}

    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
}
于 2009-09-21T09:29:53.393 回答
0

MSDN站点有一个简单清晰的模板示例,在您的情况下,这似乎是要走的路。

于 2009-09-21T19:37:29.303 回答