📄 accordion.cs
字号:
if (_panes == null)
_panes = new AccordionPaneCollection(this);
return _panes;
}
}
/// <summary>
/// Prevent the Controls property from appearing in the editor (so
/// that people will use the Panes collection instead)
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public override ControlCollection Controls
{
get { return base.Controls; }
}
#region DataBinding Properties
/// <summary>
/// Template for the Header of databound panes
/// </summary>
[Browsable(false)]
[DefaultValue(null)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(AccordionContentPanel))]
public virtual ITemplate HeaderTemplate
{
get { return _headerTemplate; }
set { _headerTemplate = value; }
}
/// <summary>
/// Template for the Content of databound panes
/// </summary>
[Browsable(false)]
[DefaultValue(null)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(AccordionContentPanel))]
public virtual ITemplate ContentTemplate
{
get { return _contentTemplate; }
set { _contentTemplate = value; }
}
/// <summary>
/// Gets or sets the data source that provides data for populating
/// the list of AccordionPanes.
/// </summary>
[Bindable(true)]
[Category("Data")]
[DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", Justification = "Assembly is not localized")]
public virtual object DataSource
{
get { return _dataSource; }
set
{
if ((value == null) || (value is IListSource) || (value is IEnumerable))
{
_dataSource = value;
OnDataPropertyChanged();
}
else
{
throw new ArgumentException("Can't bind to value that is not an IListSource or an IEnumerable.");
}
}
}
/// <summary>
/// The ID of the DataControl that this control should use to retrieve
/// its data source. When the control is bound to a DataControl, it
/// can retrieve a data source instance on-demand, and thereby attempt
/// to work in auto-DataBind mode.
/// </summary>
[DefaultValue("")]
[IDReferenceProperty(typeof(DataSourceControl))]
[Category("Data")]
[SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member", Justification = "Following ASP.NET Convention")]
public virtual string DataSourceID
{
get { return ViewState["DataSourceID"] as string ?? string.Empty; }
set
{
ViewState["DataSourceID"] = value;
OnDataPropertyChanged();
}
}
/// <summary>
/// Member in the DataSource to bind to
/// </summary>
[DefaultValue("")]
[Category("Data")]
public virtual string DataMember
{
get { return ViewState["DataMember"] as string ?? string.Empty; }
set
{
ViewState["DataMember"] = value;
OnDataPropertyChanged();
}
}
/// <summary>
/// Whether or not the Accordion was databound using the DataSourceID
/// property rather than setting the DataSource directly
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member", Justification = "Following ASP.NET Convention")]
protected bool IsBoundUsingDataSourceID
{
get { return !string.IsNullOrEmpty(DataSourceID); }
}
/// <summary>
/// Whether or not the control has already been databound, or still needs
/// to be databound
/// </summary>
protected bool RequiresDataBinding
{
get { return _requiresDataBinding; }
set { _requiresDataBinding = value; }
}
/// <summary>
/// Arguments used to request data-related operations from
/// data source controls when data is retrieved
/// </summary>
protected DataSourceSelectArguments SelectArguments
{
get
{
if (_arguments == null)
_arguments = CreateDataSourceSelectArguments();
return _arguments;
}
}
#endregion
/// <summary>
/// OnInit handler to wireup the Page's PreLoad event
/// </summary>
/// <param name="e">EventArgs</param>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Page != null)
{
Page.PreLoad += new EventHandler(this.OnPagePreLoad);
if (!IsViewStateEnabled && Page.IsPostBack)
RequiresDataBinding = true;
}
}
/// <summary>
/// OnPreLoad is used to determine whether or not we still need to databind the Accordion
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">EventArgs</param>
private void OnPagePreLoad(object sender, EventArgs e)
{
_initialized = true;
if (Page != null)
{
Page.PreLoad -= new EventHandler(this.OnPagePreLoad);
// Setting RequiresDataBinding to true in OnLoad is too late because the OnLoad page event
// happens before the control.OnLoad method gets called. So a page_load handler on the page
// that calls DataBind won't prevent DataBind from getting called again in PreRender.
if (!Page.IsPostBack)
RequiresDataBinding = true;
// If this is a postback and viewstate is enabled, but we have never bound the control
// before, it is probably because its visibility was changed in the postback. In this
// case, we need to bind the control or it will never appear. This is a common scenario
// for Wizard and MultiView.
if (Page.IsPostBack && IsViewStateEnabled && ViewState[ItemCountViewStateKey] == null)
RequiresDataBinding = true;
_pagePreLoadFired = true;
}
EnsureChildControls();
}
/// <summary>
/// Connect to the DataSourceView and determine if we still need to
/// do databinding
/// </summary>
/// <param name="e">EventArgs</param>
protected override void OnLoad(EventArgs e)
{
_initialized = true; // just in case we were added to the page after PreLoad
ConnectToDataSourceView();
if (Page != null && !_pagePreLoadFired && ViewState[ItemCountViewStateKey] == null)
{
// If the control was added after PagePreLoad, we still need to databind it because it missed its
// first change in PagePreLoad. If this control was created by a call to a parent control's DataBind
// in Page_Load (with is relatively common), this control will already have been databound even
// though pagePreLoad never fired and the page isn't a postback.
if (!Page.IsPostBack)
{
RequiresDataBinding = true;
}
// If the control was added to the page after page.PreLoad, we'll never get the event and we'll
// never databind the control. So if we're catching up and Load happens but PreLoad never happened,
// call DataBind. This may make the control get databound twice if the user called DataBind on the control
// directly in Page.OnLoad, but better to bind twice than never to bind at all.
else if (IsViewStateEnabled)
{
RequiresDataBinding = true;
}
}
base.OnLoad(e);
}
/// <summary>
/// Create the AccordionExtender and attach it to the div
/// that will be generated for this control
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "controls")]
protected override void CreateChildControls()
{
base.CreateChildControls();
// If we already have items in the ViewState, create the control
// hierarchy using the view state (and not the datasource)
if (AccordionExtender != null && ViewState[ItemCountViewStateKey] != null)
CreateControlHierarchy(false);
ClearChildViewState();
// Ensure creation of child controls
foreach (AccordionPane pane in Panes)
{
ControlCollection controls = pane.Controls;
}
}
/// <summary>
/// Mark the selected AccordionPane so it does not appear collapsed
/// </summary>
/// <param name="e">EventArgs</param>
protected override void OnPreRender(EventArgs e)
{
EnsureDataBound();
base.OnPreRender(e);
// Set the overflow to hidden to prevent any growth from
// showing initially before it is hidden by the script if
// we are controlling the height
if (AutoSize != AutoSize.None)
{
Style[HtmlTextWriterStyle.Overflow] = "hidden";
Style[HtmlTextWriterStyle.OverflowX] = "auto";
}
// Apply the standard header/content styles, but allow the
// pane's styles to take precedent
foreach (AccordionPane pane in Panes)
{
if (!string.IsNullOrEmpty(HeaderCssClass) && string.IsNullOrEmpty(pane.HeaderCssClass))
pane.HeaderCssClass = HeaderCssClass;
if (!string.IsNullOrEmpty(ContentCssClass) && string.IsNullOrEmpty(pane.ContentCssClass))
pane.ContentCssClass = ContentCssClass;
}
// Get the index of the selected pane, or use the first pane if we don't
// have a valid index and require one. (Note: We don't reset the SelectedIndex
// property because it may refer to a pane that will be added dynamically on the
// client. If we need to start with a pane visible, then we'll open the first
// pane because that's the default value used on the client as the SelectedIndex
// in this scenario.)
int index = AccordionExtender.SelectedIndex;
index = ((index < 0 || index >= Panes.Count) && AccordionExtender.RequireOpenedPane) ? 0 : index;
// Make sure the selected pane is displayed
if (index >= 0 && index < Panes.Count)
{
AccordionContentPanel content = Panes[index].ContentContainer;
if (content != null)
content.Collapsed = false;
// Set the CSS class for the open panes header
if (!string.IsNullOrEmpty(HeaderSelectedCssClass))
Panes[index].HeaderCssClass = HeaderSelectedCssClass;
}
}
/// <summary>
/// Override FindControl to look first at this control, then check each
/// of its child AccordionPanes for the control
/// </summary>
/// <param name="id">ID of the control</param>
/// <returns>Control</returns>
public override Control FindControl(string id)
{
Control ctrl = base.FindControl(id);
if (ctrl == null)
foreach (AccordionPane pane in Panes)
{
ctrl = pane.FindControl(id);
if (ctrl != null)
break;
}
return ctrl;
}
/// <summary>
/// Empty out the child Pane's collection
/// </summary>
internal void ClearPanes()
{
for (int i = Controls.Count - 1; i >= 0; i--)
if (Controls[i] is AccordionPane)
Controls.RemoveAt(i);
}
#region DataBinding
/// <summary>
/// Connects this data bound control to the appropriate DataSourceView
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -