Я пытался создать настраиваемый элемент управления, который работает точно так же, как элемент управления 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");
}
}
Задайте вопрос о том, как использовать элементы управления ASP.NET Server, и я могу ответить, я не могу вместить объяснение в это небольшое поле для комментариев.
Спасибо, Джонатан, я очень ценю вашу помощь: stackoverflow.com/questions/306381/aspnet-custom-controls
Создайте класс, наследующий System.Web.UI.Control, и переопределите метод Render (HtmlTextWriter). В этом методе визуализируйте окружающие начальные теги, затем визуализируйте дочерние элементы (RenderChildren), а затем визуализируйте конечные теги.
protected override void Render ( HtmlTextWriter output )
{
output.Write ( "<div>" );
RenderChildren ( output );
output.Write ( "</div>" );
}
Закругленные углы обычно достигаются с помощью CSS и угловых изображений для верхнего левого, верхнего правого, нижнего левого и нижнего правого углов. Это можно сделать, используя 4 вложенных div, действующих как слои, каждый из которых имеет одно угловое изображение в качестве фонового изображения.
В проекте кода есть кое-что, что может вас заинтересовать: Контейнер кривой панели - слепок настраиваемого элемента управления ASP.NET. Я уверен, что вы можете поиграть с кодом и иметь желаемое поведение и внешний вид.

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();
}
}
Еще одна вещь, которую вы можете использовать, - это расширитель закругленных углов в наборе инструментов ASP.Net ajax.
Я знаю, что это не совсем то, о чем вы просили, но вам не нужно писать собственный код.
Надеюсь, это поможет!
Здесь уже есть довольно много ответов, но я просто хотел вставить самую базовую реализацию этого, не наследуя от класса 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";
Как бы вы изменили класс SimpleContainer, если бы цель состояла в том, чтобы иметь левый контент и правильный контент? Не могли бы вы просто иметь 2 свойства ITemplate? А как насчет атрибута ParseChildren?
Отлично, это должно быть приемлемым решением. Все равно проголосовали.
Я посмотрел на этот вопрос, потому что хотел создать двухколоночную панель макета. (не совсем, но это гораздо более простой пример того, что мне нужно. Я делюсь решением, которое я использовал:
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 Content.
Если вы не хотите наследовать напрямую от 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 будет добавлен, чтобы правильно стилизовать класс Round Round.
Вероятно, это очень глупый вопрос, но, поскольку я не могу поместить этот код в типичный пользовательский элемент управления (.ascx), где бы я его поместил? Я создал класс и поместил его туда, но тогда я не знаю, как добавить его на страницу (перетаскивание просто создает ссылку)