Domanda

Ho provato a creare un controllo personalizzato che funziona esattamente come il controllo Panel, tranne che circondato da alcuni div e tale da creare un aspetto arrotondato. Non sono stato in grado di trovare un esempio decente di come farlo.

Devo essere in grado di posizionare testo e controlli all'interno del controllo e accedervi direttamente senza fare riferimento al pannello (esattamente come funziona il controllo del Pannello).

Qualcuno ha qualche esempio di questo?

È stato utile?

Soluzione

Esistono due modi per farlo. Uno è implementare INamingContainer sul tuo controllo e ci vuole molto sforzo.

L'altro modo è ereditare da Panel e sovrascrivere i metodi RenderBeginTag e RenderEndTag per aggiungere il markup personalizzato. Questo è facile.

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

Altri suggerimenti

Ci sono già alcune risposte qui, ma volevo solo incollare l'implementazione di base di questo senza ereditare dalla classe Panel. Quindi ecco qui:

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

Quindi puoi usarlo in questo modo:

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

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

E da codebehind puoi fare cose del genere:

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

Crea una classe che eredita System.Web.UI.Control e sovrascrivi il metodo Render (HtmlTextWriter). In questo metodo, esegui il rendering dei tag di inizio circostanti, quindi esegui il rendering dei figli (RenderChildren), quindi esegui il rendering dei tag di fine.

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

Gli angoli arrotondati si ottengono in genere utilizzando CSS e immagini angolari per gli angoli in alto a sinistra, in alto a destra, in basso a sinistra e in basso a destra. Si potrebbe fare usando 4 div nidificati, fungendo da livelli, ognuno con un'immagine d'angolo come immagine di sfondo.

Il progetto di codice ha qualcosa che potrebbe interessarti: Panel Curve Container - An ASP Nugget di controllo personalizzato .NET . Sono sicuro che puoi giocare con il codice e avere il comportamento e l'aspetto che desideri.

alt text

Se non vuoi ereditare direttamente da WebControl invece che da Pannello, il modo più semplice per farlo è decorare la classe con l'attributo [ParseChildren (false)] . Sebbene a prima vista ciò possa suggerire che non si desidera analizzare i bambini, ciò che il false indica in realtà è che non si desidera che i bambini vengano trattati come proprietà. Invece, vuoi che vengano trattati come controlli.

Usando questo attributo, ottieni praticamente tutte le funzionalità predefinite:

[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>");
    }
}

Ciò ti consentirà di aggiungere controlli RoundedBox alle tue pagine e aggiungere elementi secondari (controlli asp.net o HTML non elaborati) che verranno renderizzati all'interno del tuo div.

Ovviamente, i CSS verranno aggiunti per dare uno stile corretto alla classe arrotondata.

Solo un'altra cosa che puoi usare, c'è un estensione dell'angolo arrotondato nel toolkit ASP.Net ajax.

So che non è esattamente quello che hai chiesto, ma non devi scrivere alcun codice personalizzato.

Spero che ti aiuti!

Ho esaminato questa domanda perché volevo produrre un pannello di layout a 2 colonne. (non del tutto, ma è un esempio molto più semplice di ciò di cui avevo bisogno. Sto condividendo la soluzione che ho finito usando:

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
    {
    }
}

Il problema che ancora ho è che l'intellisense non funziona in questo scenario, non suggerirà i tag di contenuto destro e sinistro.

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

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top