面板曲线容器 - ASP.NET 自定义控件片段






4.79/5 (19投票s)
一个 ASP.NET 自定义面板控件,具有圆角,可最小化/最大化,显示为片段,并可用作任何内容的容器。
引言
我想要一个可以作为容器并像 System.Web.UI.WebControls.Panel <ASP:PANEL>
一样使用的控件,它具有圆角,同时具有自己的自定义标题文本。
进程
我在网上搜索了很长时间,试图找到一个与 Panel
控件类似的控件,但一直没有得到任何帮助。所以我决定自己做一个。一种方法是创建一个形成曲线的用户控件,并要求开发人员向该控件传递值,这使得整个过程过于复杂(创建太多用户控件是一项繁琐的工作,并且难以管理),同时,我也不想为了形成边界而将我的所有代码都放在用户控件中。最后,MSDN 的一个示例谈到了这样的实现,但它也有一个缺陷,即当控件用在用户控件或 DataGrid
中时会抛出错误,因为在这种情况下 ID 会被添加到子控件的前面。然后,我创建了自己的控件,并在用户控件、DataGrid
、嵌套的 DataGrid
以及许多其他方式中成功地测试了它,并且它一直都能正常工作。
特点
该控件具有以下功能
- 圆角标签页头
- 最小化图标,用于最小化标签页
- 打印图标,用于打印选定的片段
- 您可以自定义在标题中显示的标题文本
- 您可以更改顶部标签页的背景颜色或底部主体的背景颜色
- 您可以在容器内使用用户控件、自定义控件或任何 Web 控件,并且仍然可以直接在代码隐藏中访问这些控件
在代码隐藏中
protected TextBox txt;
在 aspx 中
<Tittle:PanelCurveControl ...> <asp:textbox id=txt ... /> </Tittle:PanelCurveControl>
- 此控件将在回发期间保持其最小化/最大化状态。
- 此控件可以毫无问题地用在
DataGrid
或用户控件中(其中父控件的 ID 会被添加到子控件的 ID 前面)。
如何使用它
如果您曾使用过 <asp:panel>
,那么您也可以使用这个自定义控件。
<Tittle:PanelCurveControl ID=
"Panelcurvecontrol1" runat="server" Title="My first Panel" >
Name:<br>
<asp:textbox id=txt runat=server />
</Tittle:PanelCurveControl>
上面的内容将渲染为
属性
Expandable
:使控件按需可展开。默认值:true
。RenderInBox
:在框中渲染内容。默认值:false
(仅在Expandable
为false
时使用)。将Expandable
设置为true
会使标签页消失,但如果Expandable
为false
RenderInBox
为 "true
" 会显示容器边框RenderInBox
为 "false
" 不显示边框
Closed
:可展开面板的内容是否可见Title
:作为可展开面板标题显示的文本Margin
:如果面板可展开,则使用的边距HasMinimize
:屏幕上是否显示最小化图标HasPrint
:屏幕上是否显示打印图标DefaultMinimize
:默认渲染为最小化状态还是非最小化状态BodyBackColor
:内容背景颜色TabBackColor
:顶部标签页背景颜色HeaderTextColor
:顶部标题文本颜色
一些技术细节
我继承了这个控件自 ASP:Panel
,以便它可以像 Panel
一样使用。我没有故意继承自 INamingContainer
,原因是我不希望它在每个子控件 ID 前面都加上父 ID(如果控件用在网格或用户控件中,这会产生问题)。使用了一个隐藏字段,该字段在回发期间会保留其最小化/最大化状态。我固定了一个隐藏字段 ID,以便它能在普通页面和任何控件内维护状态。
if ( this.UniqueID.IndexOf(":") >=0 )
hdn.ID = this.ID + "_hdnMinimizeState";
//Within some user control or grid
//E.g. client id will be in this case
//"UserControl1__ctl0_tblCrvPnlControl2_hdnMinimizeState"
else
hdn.ID = this.UniqueID + "_hdnMinimizeState";
//Straight on aspx page,
//E.g. client id will be in this case
//"tblCrvPnlControl1_hdnMinimizeState"
PanelCurveControl.cs:
using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.IO;
using System.Collections.Specialized;
[assembly: TagPrefix ("Tittle.Controls" , "Tittle") ]
namespace Tittle.Controls
{
#region Table Curve Panel Control (Expandable)
/// <summary>
/// Renders a tab control on page. i.e. A tabbed
/// image on top of the table and you can have ur own
/// contents in between that.
/// <example>
/// <code>
/// <Tittle:PanelCurveControl runat="server"
/// Expandable="true"
/// Width="500px"
/// Margin="10"
/// Title="Employees">
/// <table border=1>
/// <tr><td>test1</td><td>test2</td></tr>
/// <tr><td>test3</td><td>test4</td></tr>
/// </table>
/// </Tittle:PanelCurveControl>
/// </CODE>
/// </EXAMPLE>
/// <AUTHOR>Tittle Joseph (tittlejoseph@yahoo.com) India.</AUTHOR>
/// <URL>https://codeproject.org.cn/PanelCurveContainer/</URL>
/// </SUMMARY>
[ToolboxData(
"<{0}:PanelCurveControl runat=
server Expandable='true' id='tblCrvPnl' Width='200px'>")]
public class PanelCurveControl : Panel, IPostBackDataHandler
{
private string skinName = ""; //"/BasicNuggetSkin";
private bool hasMinimize = true;
private bool hasPrint = true;
private string imgPath;
private Color bodyBackColor = Color.Transparent;
private string tabBackColor = "#99CCFF";
private string headerTextColor = "black";
public PanelCurveControl() : base()
{
Expandable = true;
RenderInBox = false;
Title = "Panel";
Font.Name = "verdana";
Font.Size = FontUnit.Point(10);
Margin = 2;
Closed = false;
ForeColor = Color.Black;
BorderColor = Color.DodgerBlue;
imgPath =
HttpContext.Current.Request.ApplicationPath +
skinName + "/Images/";
//imgPath = "/Images/";
}
/// <SUMMARY>
/// Makes the control expandable on demand,
/// Default: true
/// </SUMMARY>
[Browsable(true),
Category("Validation"),
DefaultValue("true"),
Description ("Makes the control expandable on demand.") ]
public bool Expandable
{
get {return Convert.ToBoolean(ViewState["Expandable"]);}
set {ViewState["Expandable"] = value;}
}
/// <SUMMARY>
/// Render the contents in the box
/// (used only if Expandable is false),
///
/// Expandable true makes tab disappear,
/// but if Expandable is false
/// RenderInBox is "true" shows border of container.
/// RenderInBox is "false" no border appears.
/// Default: false
/// </SUMMARY>
[Browsable(true),
Category("Misc"),
DefaultValue("false"),
Description ("Render the contents in the box.") ]
public bool RenderInBox
{
get {return Convert.ToBoolean(ViewState["RenderInBox"]);}
set {ViewState["RenderInBox"] = value;}
}
/// <SUMMARY>
/// Whether the contents of the expandable panel must be visible
/// Equivalent to "DefaultMinimize" attribute
/// Default: false
/// </SUMMARY>
[Browsable(true),
Category("Validation"),
DefaultValue("false"),
Description ("Whether the contents of the " +
"expandable panel must be visible.") ]
public bool Closed
{
get {return Convert.ToBoolean(ViewState["Closed"]);}
set {ViewState["Closed"] = value;}
}
/// <SUMMARY>
/// The text displayed as the caption of the expandable panel
///
/// Default: "Panel"
/// </SUMMARY>
[Browsable(true),
Category("Behavior"),
DefaultValue("Panel"),
Description ("The text displayed as the " +
"caption of the expandable panel.") ]
public string Title
{
get {return Convert.ToString(ViewState["Title"]);}
set {ViewState["Title"] = value;}
}
/// <SUMMARY>
/// The margin to use if the panel is expandable
///
/// Default: "2"
/// </SUMMARY>
[Browsable(true),
Category("Appearance"),
DefaultValue("2"),
Description ("Margin to use if the panel is expandable.") ]
public int Margin
{
get {return Convert.ToInt32(ViewState["Margin"]);}
set {ViewState["Margin"] = value;}
}
/// <SUMMARY>
/// SkinName to be used in nugget i.e. "BasicNuggetSkin",
/// "BillInfoNuggetSkin", "DataGridNuggetSkin",
/// "TabbedNuggetSkin"
///
/// Default is "BasicNuggetSkin"
/// </SUMMARY>
[Browsable(true),
Category("Behavior"),
DefaultValue("BasicNuggetSkin"),
Description ("Skinname to be used in nugget.") ]
public string SkinName
{
get{ return skinName;}
set{ skinName = value;}
}
/// <SUMMARY>
/// Whether to show Minimize icon on screen or not.
///
/// Default: true
/// </SUMMARY>
[Browsable(true),
Category("Validation"),
DefaultValue("true"),
Description ("Whether to show minimize " +
"icon on screen or not.") ]
public bool HasMinimize
{
get{ return hasMinimize;}
set{ hasMinimize = value;}
}
/// <SUMMARY>
/// Whether to show Print icon on screen or not.
///
/// Default: true
/// </SUMMARY>
[Browsable(true),
Category("Validation"),
DefaultValue("true"),
Description ("Whether to show Print " +
"icon on screen or not.") ]
public bool HasPrint
{
get{ return hasPrint;}
set{ hasPrint = value;}
}
/// <SUMMARY>
/// Render it minmized by default or not
///
/// Default: false
/// </SUMMARY>
[Browsable(true),
Category("Appearance"),
DefaultValue("false"),
Description ("Render it minimized by default or not.") ]
public bool DefaultMinimize
{
get{ return Closed;}
set{ Closed = value;}
}
/// <SUMMARY>
/// Content Back Color
/// </SUMMARY>
public Color BodyBackColor
{
get { return bodyBackColor; }
set { bodyBackColor = value; }
}
/// <SUMMARY>
/// Top Tab Back Color
/// </SUMMARY>
public string TabBackColor
{
get { return tabBackColor; }
set { tabBackColor = value; }
}
/// <SUMMARY>
/// Top Header Text Color
/// </SUMMARY>
public string HeaderTextColor
{
get { return headerTextColor; }
set { headerTextColor = value; }
}
/// <SUMMARY>
///RaisePostDataChangedEvent::LoadPostData
/// Automatically updates the Closed property based on the content
/// of hidden field named as this control
/// </SUMMARY>
/// <PARAM name="postDataKey"</PARAM>
/// <PARAM name="postCollection"></PARAM>
/// <RETURNS></RETURNS>
public virtual bool LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
bool currentValueOfClosed = Closed;
bool postedValueOfClosed =
Convert.ToBoolean(postCollection[postDataKey+
"_hdnMinimizeState"]);
// What if the field is empty?
if (!currentValueOfClosed.Equals(postedValueOfClosed))
{
Closed = postedValueOfClosed;
return true;
}
return false;
}
/// <SUMMARY>
/// IPostBackDataHandler::RaisePostDataChangedEvent
/// </SUMMARY>
public virtual void RaisePostDataChangedEvent()
{
// Do nothing here
// No need of firing server-side events
}
/// <SUMMARY>
/// Fires when the panel gets loaded
/// </SUMMARY>
/// <PARAM name="e"></PARAM>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// Check the browser caps and disable collapse/expand if needed
bool uplevel = false;
HttpBrowserCapabilities caps = Page.Request.Browser;
if (caps.Browser.ToUpper().IndexOf("IE") > -1)
{
// This is IE. But is it at least v5?
if (caps.MajorVersion >4)
uplevel = true;
}
// If the browser is not IE5 or higher, drop collapse/expand
if (!uplevel)
{
Expandable = false;
RenderInBox = true;
}
//Need to write this, so that LoadPostData() gets called.
Page.RegisterRequiresPostBack(this);
}
/// <SUMMARY>
/// Render the control
/// </SUMMARY>
/// <PARAM name="output"></PARAM>
protected override void Render(HtmlTextWriter output)
{
if (!Expandable)
{
if (!RenderInBox)
base.Render(output);
else
RenderContentsInBox(output);
return;
}
// Add margin information if the panel is expandable
Style["margin"] = Margin.ToString();
Style["display"] = (Closed ?"none" :"");
// The internal panel must cover 100% of the parent area
// irrespective of the physical width. We change this here
// so that the original Panel code doesn't reflect the
// external width.
Unit oldWidth = Width;
Width = Unit.Percentage(100);
//Add Hidden Field to maintain
//minimize/maximize state of the curve.
TextBox hdn = new TextBox();
hdn.Attributes.Add("style","display:none");
//This is what created a big nuisance to me
if ( this.UniqueID.IndexOf(":") >=0 )
hdn.ID = this.ID + "_hdnMinimizeState";
//"UserControl1__ctl0_tblCrvPnlControl2_hdnMinimizeState"
else
hdn.ID = this.UniqueID + "_hdnMinimizeState";
//"tblCrvPnlControl1_hdnMinimizeState"
hdn.Text = Closed.ToString();
this.Controls.Add(hdn);
// Capture the default output of the Panel
StringWriter writer = new StringWriter();
HtmlTextWriter buffer = new HtmlTextWriter(writer);
base.Render(buffer);
string panelOutput = writer.ToString();
// Restore the wanted width because this affects the outer table
Width = oldWidth;
BuildControlTree(output, this.ClientID, panelOutput);
return;
}
// Handle the PreRender event
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
CreateClientScript();
}
/// <SUMMARY>
/// Build the markup for this custom Panel control
/// </SUMMARY>
/// <PARAM name="output"></PARAM>
/// <PARAM name="id"></PARAM>
/// <PARAM name="panelOutput"></PARAM>
private void BuildControlTree(HtmlTextWriter output,
string id, string panelOutput)
{
Table t = new Table();
//t.ID = "thePanel";
t.ID = id + "_thePanel";
t.CellPadding = 0;
t.CellSpacing = 0;
t.Width = Unit.Percentage(100); //Width;
t.HorizontalAlign = HorizontalAlign.Center;
t.Style.Add("margin", "0 0 0 0px");
// Prepare the topmost row
TableRow rowTop = new TableRow();
// Leftmost cell
TableCell leftCell = new TableCell();
leftCell.HorizontalAlign = HorizontalAlign.Left;
leftCell.Style.Add("width","10px");
leftCell.Style.Add("background",
tabBackColor + " url(" + imgPath +
"topleft.gif) top left no-repeat");
leftCell.Text = " ";
rowTop.Cells.Add(leftCell);
//Label Info
TableCell centerCell = new TableCell();
centerCell.Style.Add("background-Color",tabBackColor);
centerCell.Wrap = false;
centerCell.Attributes.Add("onselectstart","return false");
//Not allowing user to select Tab Title text
//through mouse or double click.
if ( hasMinimize == true )
centerCell.Attributes.Add("ondblclick",
String.Format("javascript:MinMaxTableCurvePanel('{0}')", id));
Literal lit = new Literal();
lit.Text = String.Format("{0}",Title,headerTextColor);
centerCell.Controls.Add(lit);
rowTop.Cells.Add(centerCell);
//Print Icon Cell
if ( hasPrint )
{
TableCell printCell = new TableCell();
//printCell.HorizontalAlign = HorizontalAlign.Right;
printCell.Style.Add("background-Color",tabBackColor);
printCell.Wrap = false;
printCell.Width = Unit.Pixel(20);
System.Web.UI.WebControls.Image imgPrint =
new System.Web.UI.WebControls.Image();
imgPrint.AlternateText = "Print View";
imgPrint.BorderWidth = 0;
imgPrint.Style.Add("cursor","hand");
imgPrint.Attributes.Add("onclick",
String.Format("javascript:PrintTableCurvePanel('{0}')",id));
imgPrint.ImageAlign = ImageAlign.AbsMiddle;
imgPrint.ImageUrl = imgPath + "print.gif";
printCell.Controls.Add(imgPrint);
rowTop.Cells.Add(printCell);
}
//Minimize/Maximize Icon Cell
if ( hasMinimize )
{
TableCell minimizeCell = new TableCell();
//minimizeCell.HorizontalAlign = HorizontalAlign.Right;
minimizeCell.Style.Add("background-Color",tabBackColor);
minimizeCell.Wrap = false;
minimizeCell.Width = Unit.Pixel(20);
System.Web.UI.WebControls.Image imgMinimize =
new System.Web.UI.WebControls.Image();
//imgMinimize.ID = "img";
imgMinimize.ID = id + "_imgPlusMinus";
imgMinimize.AlternateText = "Minimize/Maximize the Panel";
imgMinimize.BorderWidth = 0;
imgMinimize.Style.Add("cursor","hand");
imgMinimize.Attributes.Add("onclick",
String.Format("javascript:MinMaxTableCurvePanel('{0}')",id));
imgMinimize.ImageAlign = ImageAlign.AbsMiddle;
imgMinimize.ImageUrl =
imgPath + (Closed==true?"plus.gif":"minus.gif");
minimizeCell.Controls.Add(imgMinimize);
rowTop.Cells.Add(minimizeCell);
}
// Right most cell
TableCell rightCell = new TableCell();
rightCell.HorizontalAlign = HorizontalAlign.Right;
rightCell.Width = Unit.Pixel(10);
rightCell.Style.Add("width","10px");
rightCell.Style.Add("background",tabBackColor +
" url(" + imgPath + "topright.gif) top right no-repeat");
rightCell.Text = " ";
rowTop.Cells.Add(rightCell);
// Add the top row to the table
t.Rows.Add(rowTop);
int colspan = 3;
if ( hasPrint )
colspan++;
if ( hasMinimize )
colspan++;
// Insert the Panel's markup in the table cell {Container}
TableRow rowBody = new TableRow();
if ( bodyBackColor != Color.Transparent )
rowBody.BackColor = bodyBackColor;
TableCell cellBody = new TableCell();
cellBody.ColumnSpan = colspan;
cellBody.Text = panelOutput;
cellBody.Style.Add("BORDER","#cccccc 1px solid");
cellBody.Style.Add("padding","0 0 0 0px"); //"0 5 5 5px"
cellBody.Style.Add("margin","0 0 0 0px"); //"0 0 5 0px"
rowBody.Cells.Add(cellBody);
t.Rows.Add(rowBody);
// Output
t.RenderControl(output);
}
/// <SUMMARY>
/// Add client side scripting
/// </SUMMARY>
private void CreateClientScript()
{
string jscript = @"
<style>
P.PanelCurveTitleStyle
{
font-family:verdana;
font-size: 12px;
font-weight : bold;
text-align: center;
}
</STYLE>
<script language=javascript>
var imgPath='" + imgPath + @"';
</script>
<script language=javascript>
function MinMaxTableCurvePanel(cntrlId)
{
//Get state from hidden control.
var closed_TableCurvePanel =
document.getElementById(cntrlId+'_hdnMinimizeState').value;
if ( closed_TableCurvePanel.toLowerCase() == 'true' )
{
document.getElementById(cntrlId).style.display = '';
document.getElementById(cntrlId+'_hdnMinimizeState').value=
false;
document.getElementById(cntrlId+'_imgPlusMinus').src =
imgPath + 'minus.gif';
}
else
{
document.getElementById(cntrlId).style.display = 'none';
document.getElementById(cntrlId+'_hdnMinimizeState').value =
true;
document.getElementById(cntrlId+'_imgPlusMinus').src =
imgPath + 'plus.gif';
}
}
//TODO: this could be improved further to show tab on new window.
function PrintTableCurvePanel(cntrlId)
{
var objDiv = document.getElementById(cntrlId);
var winTableCurvePanel =
window.open('','winTableCurvePanelId','');
winTableCurvePanel.document.write('
<html><head></head><body onload=
\'javascript:window.print()\'>');
winTableCurvePanel.document.write(objDiv.innerHTML);
winTableCurvePanel.document.write('</body></html>');
winTableCurvePanel.focus();
}
</script>
";
if (!Page.IsClientScriptBlockRegistered("TableCurvePanel_Script"))
Page.RegisterClientScriptBlock("TableCurvePanel_Script",
jscript );
}
/// <SUMMARY>
/// Render the panel in a box (MSDN like)
/// </SUMMARY>
/// <PARAM name="output"></PARAM>
private void RenderContentsInBox(HtmlTextWriter output)
{
this.Style.Add("BORDER","#cccccc 1px solid");
this.Style.Add("padding","0 0 0 0px"); //"0 5 5 5px"
this.Style.Add("margin","0 0 0 0px"); //"0 0 5 0px"
base.Render(output);
}
}
#endregion
}
顶部显示的图片的 ASPX 代码
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="PanelCurveContainer.WebForm1" %>
<%@Register TagPrefix="Tittle" namespace="Tittle.Controls"
Assembly="ClassLibrary1" %>
<%@Register TagPrefix="Tittle" TagName=
"WebUserControl" Src="WebUserControl1.ascx" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<title>WebForm1</title>
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<Tittle:PanelCurveControl ID="Panelcurvecontrol1"
runat="server" Expandable="true" Margin="10"
Title="Panel Curve - Custom Tab Color"
TabBackColor="#FF9933">
<table width=90% align=center><tr>
<td><font size=-1>Name:</font>
<asp:textbox id="Textbox1" runat=server /> </td>
<td><font size=-1>Age:</font>
<input type=text /></td>
</tr></table> </font>
</Tittle:PanelCurveControl>
<br>
<Tittle:PanelCurveControl ID="Panelcurvecontrol2"
runat="server" Expandable="true"
Title="Panel Curve - Custom Header Text Color and Content Back Color"
BodyBackColor="Pink" HeaderTextColor="#009900">
Content here
</Tittle:PanelCurveControl>
<br>
<table width="95%" border=0 align=center>
<tr>
<td valign=top>
<Tittle:PanelCurveControl ID="Panelcurvecontrol3"
runat="server" Expandable="true"
Title="Panel Curve - Without Print Icon"
HasPrint="False" BodyBackColor="#CCFFFF" >
Name:<br>
<asp:textbox id=txt runat=server />
</Tittle:PanelCurveControl>
<br>
<Tittle:PanelCurveControl ID="Panelcurvecontrol4"
runat="server" Expandable="true"
Title="Panel Curve - Without Any Icon"
HasPrint="False" HasMinimize="false"
HeaderTextColor="#009900" TabBackColor="#FFCC99">
Content here
</Tittle:PanelCurveControl>
</td>
<td valign=top>
<Tittle:PanelCurveControl ID="Panelcurvecontrol5"
runat="server" Expandable="true"
Title="Panel Curve - Master Curve"
HasMinimize="false" HasPrint="false"
HeaderTextColor="pink" TabBackColor="green" >
More Panels
<table width="100%">
<tr>
<td valign=top >
<Tittle:PanelCurveControl ID="Panelcurvecontrol7"
runat="server" Expandable="true"
Title="Panel Curve - Master Curve - Child 1"
HasMinimize="false" HasPrint="false"
HeaderTextColor="#666600" TabBackColor="#CCFFCC" >
One More Child
<Tittle:PanelCurveControl ID="Panelcurvecontrol8"
runat="server" Expandable="true"
Title="Panel Curve - Master Curve - Child 1 - Child 1"
HasPrint="false" HeaderTextColor="white"
TabBackColor="#336699" >
Content here
</Tittle:PanelCurveControl>
</Tittle:PanelCurveControl>
</td>
</tr>
</table>
</Tittle:PanelCurveControl>
</td></tr>
</table>
<tittle:WebUserControl id="WebUserControl1" runat="server" />
<br><br>
<br>
</form>
</body>
</html>
结论
我非常乐意知道这段代码是否在任何方面帮助了您,请不要犹豫或偷懒,留下您的评论,告诉您对这个提交的感受以及它在多大程度上帮助了您。如果您在使用此控件的代码中保留此页面的 URL,我将不胜感激。
历史
- 2005 年 11 月 15 日:创建