0

我正在尝试学习如何使用 ITemplate 来获得更好的自定义控件。我大部分时间都在工作,但我无法弄清楚如何从页面访问容器的任何属性。

这是我的模板控件:

[ParseChildren(true)]
[PersistChildren(false)]
public partial class Example : UserControl
{
    private ITemplate _CustomPanelContainer;

    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateContainer(typeof(CustomPanelContainer))]
    [TemplateInstance(TemplateInstance.Single)]
    public virtual ITemplate CustomPanel
    {
        get { return _CustomPanelContainer; }
        set { _CustomPanelContainer = value; }
        
    }


    protected override void CreateChildControls()
    {
        Controls.Clear();
        if (_CustomPanelContainer != null)
        {
            var p = new Panel();
            p.ID = "CustomPanel";
            Controls.Add(p);
            _CustomPanelContainer.InstantiateIn(p);
        }
        base.CreateChildControls();
    }


    public class CustomPanelContainer : Panel, INamingContainer 
    {
        
        private string _Test = "TESTING!";
        public string TextTest 
        { 
            get 
            { 
                return _Test;
            }
            set
            {
                _Test = value;
            }
        }
    }
}

这是页面实现:

<uc1:Example runat="server" ID="Example1">
        <CustomPanel>
            <strong>Test: </strong> <%# Container.TextTest %>
        </CustomPanel>
    </uc1:Example>

它大部分都在工作,但问题是 <%# Container.TextTest %> 总是返回一个空字符串。当我在调试器上运行它时,我在 CustomPanelContainer 的 TextTest 属性内的行中放置了一个断点,并且断点永远不会被命中,因此该属性实际上永远不会被访问。

我在这里想念什么?如何通过 <%#Container 启用对容器公共属性的访问?

4

1 回答 1

0

我终于想出了如何让它按照我想要的方式运行。

我删除了 ITemplate 作为 Container 的类型,并将类型设置为实际类型,并在 CreateChildControls() 中添加了 DataBind() 命令。

也许不是完全正确的方法,但它确实有效。

让问题保持开放,看看是否有人提出任何批评或更好的方法,因为我真的不知道我在这里做什么。

简化工作代码:

[ParseChildren(true)]
[PersistChildren(false)]
public partial class Example : UserControl
{

    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateInstance(TemplateInstance.Single)]
    public virtual CustomPanelContainer Template { get; set; }


    protected override void CreateChildControls()
    {
        Controls.Clear();
        if (Template != null)
        {
            Template.DataBind();
            Controls.Add(Template);
        }
        base.CreateChildControls();
    }

    

    public class CustomPanelContainer : Panel, INamingContainer
    {
        public string TextTest
        {
            get { return "TESTING!"; }
        }
    }
}

页面实现:

<uc1:Example runat="server" ID="Example">
    <Template>
        <strong>Test: </strong><span><%# Container.TextTest %></span>
    </Template>
</uc1:Example>

编辑:这也适用于需要隐藏模板的类型。即,上面的代码公开了模板的类型以允许将面板的属性作为模板的属性进行操作,而下面的代码隐藏了模板的类型以阻止对其属性的操作。

[ParseChildren(true)]
[PersistChildren(false)]
public partial class Example : UserControl
{

    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateInstance(TemplateInstance.Single)]
    [TemplateContainer(typeof(CustomPanelContainer))]
    public virtual ITemplate Template { get; set; }


    protected override void CreateChildControls()
    {
        Controls.Clear();
        if (Template != null)
        {
            var p = new CustomPanelContainer();
            Template.InstantiateIn(p);
            p.DataBind();
            Controls.Add(p);
        }
        base.CreateChildControls();
    }

    

    public class CustomPanelContainer : Panel, INamingContainer
    {
        public string TextTest
        {
            get { return "TESTING!"; }
        }
    }
于 2021-10-22T17:46:28.473 回答