Пользовательский элемент управления контейнером ASP.NET

StackOverflow https://stackoverflow.com/questions/306288

  •  08-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

Есть два способа сделать это. Одним из них является реализация 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>

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

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

Создайте класс, который наследует System.Web.UI.Control, и переопределите метод Render (HtmlTextWriter). В этом методе визуализируйте окружающие начальные теги, затем визуализируйте дочерние (RenderChildren), а затем визуализируйте конечные теги.

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

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

В проекте Code есть кое-что, что может вас заинтересовать: Контейнер кривой панели - ASP Слепок .NET Custom Control . Я уверен, что вы можете поиграть с кодом и вести себя так, как вам хочется.

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 будет добавлен, чтобы правильно оформить класс закругленной коробки.

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

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

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

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

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 в этом сценарии не работает, в нем не будут предложены теги содержимого Left и Right.

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();
    }

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top