Изготовленный на заказ контейнер ASP.NET контроль

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

Мне нужно иметь возможность размещать текст и элементы управления внутри элемента управления и обращаться к нему напрямую без ссылки на панель (точно так же, как работает панель управления).

У кого-нибудь есть примеры этого?

8 ответов


есть два способа сделать это. Один из них-реализовать INamingContainer на вашем элементе управления, и это требует больших усилий.

другой способ-наследовать от Panel и переопределить методы RenderBeginTag и RenderEndTag для добавления пользовательской разметки. Это просто.

public class RoundedCornersPanel : System.Web.UI.WebControls.Panel
{
    public override RenderBeginTag (HtmlTextWriter writer)
    {
        writer.Write("Your rounded corner opening markup");
        base.RenderBeginTag(writer);
    }

    public override RenderEndTag (HtmlTextWriter writer)
    {
        base.RenderEndTag(writer);
        writer.Write("Your rounded corner closing markup");                     
    }
}

здесь уже довольно много ответов, но я просто хотел вставить самую базовую реализацию этого, не наследуя от класса Panel. Так вот оно:

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

[ToolboxData("<{0}:SimpleContainer runat=server></{0}:SimpleContainer>")]
[ParseChildren(true, "Content")]
public class SimpleContainer : WebControl, INamingContainer
{
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateContainer(typeof(SimpleContainer))]
    [TemplateInstance(TemplateInstance.Single)]
    public virtual ITemplate Content { get; set; }

    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        // Do not render anything.
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        // Do not render anything.
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
        output.Write("<div class='container'>");
        this.RenderChildren(output);
        output.Write("</div>");
    }

    protected override void OnInit(System.EventArgs e)
    {
        base.OnInit(e);

        // Initialize all child controls.
        this.CreateChildControls();
        this.ChildControlsCreated = true;
    }

    protected override void CreateChildControls()
    {
        // Remove any controls
        this.Controls.Clear();

        // Add all content to a container.
        var container = new Control();
        this.Content.InstantiateIn(container);

        // Add container to the control collection.
        this.Controls.Add(container);
    }
}

тогда вы можете использовать его следующим образом:

<MyControls:SimpleContainer
    ID="container1"
    runat="server">
    <Content>
        <asp:TextBox
            ID="txtName"
            runat="server" />

        <asp:Button
            ID="btnSubmit"
            runat="server"
            Text="Submit" />
    </Content>
</MyControls:SimpleContainer>

и из codebehind вы можете делать такие вещи:

this.btnSubmit.Text = "Click me!";
this.txtName.Text = "Jack Sparrow";

создайте класс, наследующий System.Сеть.ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС.Управление и переопределение метода Render ( HtmlTextWriter). В этом методе визуализируйте окружающие начальные теги, затем визуализируйте дочерние(RenderChildren), затем визуализируйте конечные теги.

protected override void Render ( HtmlTextWriter output )
{
  output.Write ( "<div>" );
  RenderChildren ( output );
  output.Write ( "</div>" );
}

закругленные углы обычно достигаются с помощью CSS и угловых изображений для верхнего левого, верхнего правого, нижнего левого и нижнего правого углов. Это можно сделать, используя 4 вложенных divs, действуя как слои, каждый из которых имеет одно угловое изображение в качестве фона изображение.


код проекта есть что-то, что может вас заинтересовать : контейнер Кривой панели-An ASP.NET пользовательский контроль Nugget. Я уверен, что вы можете играть с кодом и иметь поведение и смотреть, что хотите.

alt text


Если вы не хотите наследовать непосредственно от WebControl, а не от Panel, самый простой способ сделать это-украсить класс атрибутом [ParseChildren(false)]. Хотя на первый взгляд это может означать, что вы не хотите разбирать детей, какого false фактически указывает, что вы не хотите, чтобы дети рассматривались как свойства. Вместо этого, вы хотите, чтобы они рассматривались как элементы управления.

используя этот атрибут, вы получаете практически все функции из коробка:

[ToolboxData("<{0}:RoundedBox runat=server></{0}:RoundedBox>")]
[ParseChildren(false)]
public class RoundedBox : WebControl, INamingContainer
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.Write("<div class='roundedbox'>");
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        writer.Write("</div>");
    }
}

Это позволит вам добавить элементы управления RoundedBox на ваши страницы и добавить детей (либо asp.net элементы управления или необработанный html), которые будут отображаться внутри вашего div.

конечно, css будет добавлен для правильного стиля класса roundedbox.


еще одна вещь, которую вы можете использовать, есть расширитель закругленного угла в ASP.Net AJAX toolkit.

Я знаю, что это не совсем то, что вы просили, но вам не нужно писать пользовательский код.

надеюсь, что это поможет!


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

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Syn.Test
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:MultiPanel runat=server></{0}:MultiPanel>")]
    [ParseChildren(true)]
    [PersistChildren(false)]
    public class MultiPanel : WebControl, INamingContainer
    {
        public ContentContainer LeftContent { get; set; }

        public ContentContainer RightContent { get; set; }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
        }

        protected override void Render(HtmlTextWriter output)
        {
            output.AddStyleAttribute("width", "600px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);

            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "280px");
            output.AddStyleAttribute("padding", "10px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            LeftContent.RenderControl(output);
            output.RenderEndTag();

            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "280px");
            output.AddStyleAttribute("padding", "10px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            RightContent.RenderControl(output);
            output.RenderEndTag();

            output.RenderEndTag();
         }
    }

    [ParseChildren(false)]
    public class ContentContainer : Control, INamingContainer
    {
    }
}

проблема, которую я все еще имею, - intellisense не работает в этом сценарии, он не будет предлагать левые и правые теги содержимого.


public class myCustomPanel : Panel
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "top_left_corner");
        writer.RenderBeginTag(HtmlTextWriterTag.Div);
            base.RenderBeginTag(writer);
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
            base.RenderEndTag(writer);
        writer.RenderEndTag();
    }

}