📄 tabcontainerdesigner.cs
字号:
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web.UI.Design;
using AjaxControlToolkit;
using AjaxControlToolkit.Design;
using System.ComponentModel;
using System.Collections.Generic;
using System;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms;
using System.Text;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.ComponentModel.Design.Serialization;
namespace AjaxControlToolkit
{
/// <summary>
/// Control Designer for the TabContainer
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2117:AptcaTypesShouldOnlyExtendAptcaBaseTypes", Justification = "Security handled by base class")]
public class TabContainerDesigner : System.Web.UI.Design.ControlDesigner
{
/// <summary>
/// Our HTML templates for design time.
/// </summary>
private const string TabLink = "<a style='padding:2px;border-top:thin white inset;border-left:thin white inset; border-right:thin white inset;;' href='#'>{0}</a>";
private const string ActiveTabLink = "{0}";
private const string ClickRegionHtml = @"<div style='float:left;padding:2px;color:{3}; background-color:{4};{5};height:1em;' {0}='{1}'>{2}</div>";
private const string DesignTimeHtml =
@"<div style=""padding:2px;width:{7};height:{8}"">
<div style='text-align:center;color:{0}; background-color:{1};border-left:thin white outset; border-right:thin white outset;height:1em;'>{2}</div>
<div style='color:{3}; background-color:{4};border-left:thin white outset; border-right:thin white outset;height:1em;text-align:left;'>{5}</div>
<div style='clear:both;text-align:left;border-left:thin white outset; border-bottom:thin white outset; border-right:thin white outset;background-color:{10};height:100%;' {9}='0'>{6}</div>
</div>";
private const string EmptyDesignTimeHtml =
@"<div style='display:inline-block;padding:2px;'>
<div style='color:{0}; background-color:{1};border-left:thin white outset; border-right:thin white outset;'>{2}</div>
<div style=""text-align:center;border-left:thin white outset; border-bottom:thin white outset; border-right:thin white outset;"" {3}='0'>
<a href='#'>Add New Tab</a></div>
</div>";
private const string AddTabName = "#addtab";
/// <summary>
/// Initializes a new instance of the TabContainerDesigner class
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
public TabContainerDesigner()
{
}
/// <summary>
/// Helper property to get the TabContainer we're designing.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
private TabContainer TabContainer
{
get
{
return (TabContainer)Component;
}
}
/// <summary>
/// Create and return our action list - this is what creates the flyout panel with the verb commands
/// </summary>
public override DesignerActionListCollection ActionLists
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
get
{
DesignerActionListCollection actionLists = new DesignerActionListCollection();
actionLists.AddRange(base.ActionLists);
actionLists.Add(new TabContainerDesignerActionList(this));
return actionLists;
}
}
/// <summary>
/// Sets or gets the current tab ID. If this is set,
/// it will locate the tab and notify the designer of the change.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
private string CurrentTabID
{
set
{
if (!String.IsNullOrEmpty(value))
{
TabPanel panel = TabContainer.FindControl(value) as TabPanel;
if (panel == null)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Can't find child tab '{0}'", value));
}
int index = -1;
// find the index. we set by index so that the
// ActiveTabIndex property will get changed, which makes Undo/Redo happy.
//
TabContainer tc = TabContainer;
for (int i = 0; i < tc.Tabs.Count; i++)
{
if (tc.Tabs[i] == panel)
{
index = i;
break;
}
}
Debug.Assert(index != -1, "Couldn't find panel in list!");
if (index != -1)
{
TypeDescriptor.GetProperties(tc)["ActiveTabIndex"].SetValue(tc, index);
}
}
UpdateDesignTimeHtml();
}
}
/// <summary>
/// Tell the designer we're creating our own UI.
/// </summary>
protected override bool UsePreviewControl
{
get
{
return true;
}
}
/// <summary>
/// This is the main worker function for the designer.
///
/// It figures out what the HTML shape of the design-time object should be.
///
/// There are three major pieces to this
///
/// 1. The outer main HTML
/// 2. The HTML that makes up the design time tabs
/// 3. The HTML that is the content for the current tab
///
/// Attached to several of these bits of markup are DesignerRegions. Some regions are editable,
/// some are there just to catch clicks to change tabs or add new tabs.
/// </summary>
/// <param name="regions"></param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
public override string GetDesignTimeHtml(DesignerRegionCollection regions)
{
if (regions == null)
{
throw new ArgumentNullException("regions");
}
if (TabContainer.ActiveTab != null)
{
// create the main editable region
//
EditableDesignerRegion region = new EditableDesignerRegion(this, String.Format(CultureInfo.InvariantCulture, "c{0}", TabContainer.ActiveTab.ID));
regions.Add(region);
// build out the content HTML. We'll need this later.
//
string contentHtml = GetTabContent(TabContainer.ActiveTab, true);
StringBuilder clickRegions = new StringBuilder();
// now build out the design time tab UI.
//
// we do this by looping through the tabs and either building a link for clicking, and a plain DesignerRegion, or,
// we build a plain span an attach an EditableDesigner region to it.
int count = 2; // start with two since we've already got two regions. these numbers need to correspond to the order in the regions collection
foreach (TabPanel tp in TabContainer.Tabs)
{
bool isActive = tp.Active;
string headerText = GetTabContent(tp, false);
// Build out the HTML for one of the tabs. No, I don't usually write code like this, but this is just kind
// of icky no matter how you do it. Nothing to see here.
//
clickRegions.AppendFormat(CultureInfo.InvariantCulture, ClickRegionHtml,
DesignerRegion.DesignerRegionAttributeName,
(isActive ? 1 : count), // if it's the editable one, it has to be index 1, see below
String.Format(CultureInfo.InvariantCulture, isActive ? ActiveTabLink : TabLink, headerText),
ColorTranslator.ToHtml(SystemColors.ControlText),
(isActive ? ColorTranslator.ToHtml(SystemColors.Window) : "transparent"),
(isActive ? "border-top:thin white outset;border-left:thin white outset;border-right:thin white outset;" : "")
);
// the region names are arbitrary. for this purpose, we encode them by a letter - h or t for header or tab, respectively,
// and then pop on the tab ID.
//
if (isActive) {
// the editable header region is always to be 1, so we insert it there.
//
regions.Insert(1, new EditableDesignerRegion(this, String.Format(CultureInfo.InvariantCulture, "h{0}", tp.ID)));
}
else {
// otherwise, just create a plain region.
//
DesignerRegion clickRegion = new DesignerRegion(this, String.Format(CultureInfo.InvariantCulture, "t{0}", tp.ID));
clickRegion.Selectable = true;
count++;
regions.Add(clickRegion);
}
}
// OK build out the final full HTML for this control.
//
StringBuilder sb = new StringBuilder(1024);
sb.Append(String.Format(CultureInfo.InvariantCulture,
DesignTimeHtml,
ColorTranslator.ToHtml(SystemColors.ControlText),
ColorTranslator.ToHtml(SystemColors.ControlDark),
TabContainer.ID,
ColorTranslator.ToHtml(SystemColors.ControlText),
ColorTranslator.ToHtml(SystemColors.Control),
clickRegions.ToString(),
contentHtml,
TabContainer.Width,
TabContainer.Height,
DesignerRegion.DesignerRegionAttributeName,
ColorTranslator.ToHtml(SystemColors.Window)
));
return sb.ToString();
}
else
{
// build the empty tab html.
StringBuilder sb = new StringBuilder(512);
sb.AppendFormat(CultureInfo.InvariantCulture, EmptyDesignTimeHtml,
ColorTranslator.ToHtml(SystemColors.ControlText),
ColorTranslator.ToHtml(SystemColors.ControlDark),
TabContainer.ID,
DesignerRegion.DesignerRegionAttributeName);
// add a designer region for the "AddTab" UI.
//
DesignerRegion dr = new DesignerRegion(this, AddTabName);
regions.Add(dr);
return sb.ToString();
}
}
/// <summary>
/// The Designer will call us back on this for each EditableDesignerRegion that we created.
/// In this we return the markup that we want displayed in the editable region.
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
public override string GetEditableDesignerRegionContent(EditableDesignerRegion region)
{
if (region == null)
{
throw new ArgumentNullException("region");
}
string regionName = region.Name;
Debug.Assert(regionName[0] == 'c' || regionName[0] == 'h', "Expected regionName to start with c or h, not " + regionName);
// is it a content template or a header?
//
bool content = regionName[0] == 'c';
regionName = regionName.Substring(1);
TabPanel activeTab = (TabPanel)TabContainer.FindControl(regionName);
Debug.Assert(activeTab != null, "Couldn't find tab " + regionName);
return GetTabContent(activeTab, content);
}
/// <summary>
/// Helper method to instantiate the given template into a control
/// an slurp out the markup.
/// </summary>
/// <param name="template"></param>
/// <param name="id"></param>
/// <returns></returns>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -