如何创建模拟switch / case的ASP.NET控件?

时间:2009-09-21 09:02:38

标签: asp.net web-controls

我有一个转发器循环遍历不同类型的对象列表。我想根据类型不同地渲染对象。为此,我需要某种控制(因为我想避免使用代码隐藏),其行为类似于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>

5 个答案:

答案 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网站有一个简单明确的模板示例,看起来似乎就像你的情况一样。