Не удается неявно преобразовать тип 'System.Web.UI.CompiledTemplateBuilder' в пользовательский ITemplate

1

Когда вы создаете ListView, в элементе управления есть свойство, которое позволяет вам указать идентификатор PlaceHolder в LayoutTemplate, который используется для хранения элементов управления для каждого элемента.

<asp:ListView ID="lvTest" runat="server" ItemPlaceholderID="testPlaceholder">
    <LayoutTemplate>
        <ul>
            <asp:PlaceHolder ID="testPlaceholder" runat="server" />
        </ul>
    </LayoutTemplate>
    <ItemTemplate>
        <li>Item</li>
    </ItemTemplate>
</asp:ListView>

Я пытаюсь создать собственный шаблонный серверный элемент управления, но хотел бы иметь свойство в самом шаблоне, так как я ожидаю, что у меня будет несколько разных шаблонов. Мой чрезвычайно упрощенный, тривиальный пример:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ControlLibrary
{
    [ParseChildren(true)]
    public class TestContainer : Control, INamingContainer
    {
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(TestContainer))]
        public TestTemplate TestTemplate { get; set; }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            DataBind();
        }

        public override void DataBind()
        {
            base.DataBind();

            CreateChildControls();
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();

            var phTest = new PlaceHolder();
            phTest.ID = "phTest";

            Controls.Add(phTest);

            if (this.TestTemplate != null)
                this.TestTemplate.InstantiateIn(phTest);

            this.ChildControlsCreated = true;
        }
    }

    public class TestTemplate : ITemplate
    {
        public string Name { get; set; }

        public void InstantiateIn(Control container)
        {
            container.Controls.Add(new LiteralControl(this.Name));
        }
    }
}

Однако, если я добавлю шаблон в мой.aspx файл, как показано ниже, я получаю сообщение об ошибке CS0029: Невозможно неявно преобразовать тип 'System.Web.UI.CompiledTemplateBuilder' в 'ControlLibrary.TestTemplate'

<CustomControls:TestContainer ID="testContainer" runat="server">
    <TestTemplate>
        test
    </TestTemplate>
</CustomControls:TestContainer>

Можно ли это сделать или мне нужно будет поместить все настраиваемые свойства в родительский контейнер?

Спасибо за любую помощь, которую вы можете предоставить!

Теги:
webforms
custom-controls

1 ответ

2
Лучший ответ

Вы сделали все правильно, кроме объявления свойства шаблона. Любой шаблон должен быть объявлен как System.Web.UI.ITemplate. Просто замените объявление шаблона:

public ITemplate TestTemplate { get; set; }

И он должен начать работать. Для справки см. Как создать шаблонные пользовательские элементы управления ASP.NET.

Чтобы сделать трюк с настраиваемыми атрибутами для шаблона, вам нужно добавить еще один класс, наследующий из коллекции:

public class TestTemplateList : List<TestTemplate> { }

И измените объявление элемента управления следующим образом:

[ParseChildren(true, DefaultProperty = "TestTemplates")]
public class TestContainer : Control, INamingContainer
{
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public TestTemplateList TestTemplates { get; set; }

    // ... OnLoad and DataBind left intact

    protected override void CreateChildControls()
    {
        Controls.Clear();

        var phTest = new PlaceHolder();
        phTest.ID = "phTest";

        Controls.Add(phTest);

        if (this.TestTemplates != null)
        {
            foreach (var testTemplate in TestTemplates)
            {
                ((ITemplate)testTemplate).InstantiateIn(phTest);    
            }
        }

        this.ChildControlsCreated = true;
    }
}

После этого вы сможете объявить контроль в обоих направлениях. Вы можете пропустить указание TestTemplates поскольку оно объявлено как DefaulProperty в ParseChildrenAttribute:

<CustomControls:TestContainer runat="server" ID="testContainer">
    <CustomControls:TestTemplate Name="test">
    </CustomControls:TestTemplate>
</CustomControls:TestContainer>

<%-- OR --%>

<CustomControls:TestContainer runat="server" ID="wc11">
    <TestTemplates>
        <CustomControls:TestTemplate Name="test">
        </CustomControls:TestTemplate>
    </TestTemplates>
</CustomControls:TestContainer>
  • 0
    Спасибо за ответ! Изменение типа свойства на ITemplate позволяет странице загружаться без ошибок, но я все еще не уверен, как добавить свойство к самому шаблону. Это возможно? Например, я хотел бы иметь <TestTemplate Name = "test"> вместо <TestTemplate>.
  • 0
    @ JKasper11 Я обновил свой ответ. Вам нужно сделать небольшой трюк с контейнером по умолчанию для TestTemplate .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню