Как создать элемент управления ASP.NET, который имитирует переключатель / регистр? - PullRequest
1 голос
/ 21 сентября 2009

У меня есть повторитель, перебирающий список объектов разных типов. Я хотел бы визуализировать объекты по-разному в зависимости от их типа. Для этого мне нужен какой-то элемент управления (так как я хочу избежать использования выделенного кода), который имеет поведение, похожее на оператор 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> и как-то указать его для основного веб-элемента управления?

Буду благодарен за любые ссылки, ссылки на учебники и т. Д.

Альтернатива

В качестве альтернативы предложите более удобный способ рендеринга различных элементов управления 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 ]

1 голос
/ 21 сентября 2009

Посмотрите на реализацию интерфейса 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>
1 голос
/ 21 сентября 2009

Элемент управления MultiView является ближайшей готовой инструкцией в ASP.NET к оператору переключения C #.

0 голосов
/ 21 сентября 2009

На сайте MSDN есть простой наглядный пример создания шаблонов, и это, безусловно, похоже на путь в вашем случае.

0 голосов
/ 21 сентября 2009

Некоторое время назад у меня было похожее требование, и я сделал нечто похожее на:

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

защищенный TypedTemplate GetTemplate (объект dataItem) { if (dataItem == null) { вернуть ноль; } foreach (шаблон TypedTemplate в шаблонах) { Тип 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 является StateManagedCollection класса TypedTemplate:

[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
}
0 голосов
/ 21 сентября 2009

Почему бы вам не отказаться от управления сервером и не использовать оператор C # switch. Все, что вам нужно, это обернуть его в теги кода.

Другим подходом является итерация (для цикла). Создайте интерфейс со свойством типа и методом визуализации. Затем перебирайте интерфейсы, пока не найдете правильный тип.

...