代码之家  ›  专栏  ›  技术社区  ›  Blixt

如何创建模拟开关/案例的ASP.NET控件?

  •  1
  • Blixt  · 技术社区  · 15 年前

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

    我以前做过web控件,但这是一个相当复杂的控件。。。

    • 如何使其支持多个 <Case> 元素?
    • 是否有可能实施该计划 <Case Type="..."> 元素,还是仅限于属性较少的元素?

    我猜我得为这部电影打个字 <案例> 元素并以某种方式为主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 回复  |  直到 4 年前
        1
  •  1
  •   Joe Chung    15 年前
        2
  •  1
  •   Jan Remunda    15 年前

    看看 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>
    
        3
  •  0
  •   Chuck Conway    15 年前

    为什么不放弃服务器控件,使用C#switch语句呢。您只需将其包装在代码标记中。

        4
  •  0
  •   veggerby    15 年前

    我不久前也有类似的要求,我做了类似的事情:

    [ParseChildren(true, "Templates")]
    public class TypedRepeater : CompositeDataBoundControl
    {
        [
        PersistenceMode(PersistenceMode.InnerProperty),
        Browsable(false),
        MergableProperty(false)
        ]
        public TypedTemplateCollection Templates
        {
            get;
        }
    

    受保护的TypedTemplate GetTemplate(对象数据项) { if(dataItem==null) { } { 类型itemType=dataItem.GetType(); { 返回模板; } 返回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
    }
    
        5
  •  0
  •   pthalacker    15 年前

    这个 MSDN 该网站有一个简单明了的模板示例,在您的案例中,它看起来确实是一种方式。

    推荐文章