[fix]Config创建默认配置文件的开关Runtime.CreateConfigOnMissing,仅需对自动创建生效,而不应该阻止用户主动Save
智能大石头 编写于 2024-08-09 00:30:41 石头 提交于 2024-08-10 14:22:24
X
// Table.cs

// Copyright (C) 2013 Pedro Fernandes

// This program is free software; you can redistribute it and/or modify it under the terms of the GNU 
// General Public License as published by the Free Software Foundation; either version 2 of the 
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 
// the GNU General Public License for more details. You should have received a copy of the GNU 
// General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 
// Temple Place, Suite 330, Boston, MA 02111-1307 USA

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq;

namespace NewLife.Bootstrap.Controls
{
    [ToolboxData("<{0}:Table runat=server />")]
    [ParseChildren(true, "Footer")]
    [PersistChildren(false)]
    public class Table : DataBoundControl, INamingContainer
    {

        private System.Web.UI.WebControls.Table table = new System.Web.UI.WebControls.Table();
        private List<BoundColumn> _Columns = new List<BoundColumn>();

        /// <summary>
        /// Initializes a new instance of the <see cref="Table" /> class.
        /// </summary>
        public Table()
        {
            this.Zebra = false;
            this.Condensed = false;
        }

        #region CssClass method

        string sCssClass = "";

        /// <summary>
        /// Adds the CSS class.
        /// </summary>
        /// <param name="cssClass">The CSS class.</param>
        private void AddCssClass(string cssClass)
        {
            if (String.IsNullOrEmpty(this.sCssClass))
            {
                this.sCssClass = cssClass;
            }
            else
            {
                this.sCssClass += " " + cssClass;
            }
        }

        #endregion

        /// <summary>
        /// Gets the tab pages.
        /// </summary>
        /// <value>
        /// The tab pages.
        /// </value>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public List<BoundColumn> Columns
        {
            get { return _Columns; }
        }

        /// <summary>
        /// Gets or sets the content.
        /// </summary>
        /// <value>
        /// The content.
        /// </value>
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(Table))]
        [TemplateInstance(TemplateInstance.Single)]
        public virtual ITemplate Footer
        {
            get;
            set;
        }

        [Category("Appearance")]
        [DefaultValue(false)]
        public bool Zebra
        {
            get { return (bool)ViewState["Zebra"]; }
            set { ViewState["Zebra"] = value; }
        }

        [Category("Appearance")]
        [DefaultValue(false)]
        public bool Condensed
        {
            get { return (bool)ViewState["Condensed"]; }
            set { ViewState["Condensed"] = value; }
        }

        [Category("Appearance")]
        [DefaultValue(null)]
        public Paginator Pagination
        {
            get;
            set;
        }

        /// <summary>
        /// Sets the paginator.
        /// </summary>
        /// <param name="retrievedData">The retrieved data.</param>
        private void SetPaginator(ref System.Collections.IEnumerable retrievedData)
        {
            if (this.Pagination == null)
            {
                return;
            }

            int intItemCount = retrievedData.Cast<object>().Count();

            if (intItemCount == 0)
            {
                throw new NullReferenceException("DataSource is empty.");
            }
            else
            {
                this.Pagination.ItemCount = intItemCount;
            }

            retrievedData = retrievedData.Cast<object>()
                 .Skip(this.Pagination.PageSize * this.Pagination.CurrentPageIndex)
                 .Take(this.Pagination.PageSize);
        }
        
        /// <summary>
        /// Performs the data binding.
        /// </summary>
        /// <param name="retrievedData">The retrieved data.</param>
        protected override void PerformDataBinding(System.Collections.IEnumerable retrievedData)
        {
            table.Rows.Clear();

            base.PerformDataBinding(retrievedData);

            if (this.Columns.Count == 0)
            {
                throw new Exception("List of columns is null or empty.");
            }

            if (retrievedData == null)
            {
                return;
            }

            this.SetPaginator(ref retrievedData);

            TableRow rowHeader;
            TableRow row;

            rowHeader = new TableRow();
            rowHeader.TableSection = TableRowSection.TableHeader;

            foreach (BoundColumn boundColumn in this.Columns)
            {
                if (!DesignMode && TypeDescriptor.GetProperties(retrievedData.Cast<object>().First()).Find(boundColumn.FieldName, false) == null)
                {
                    throw new NullReferenceException(String.Format("Column with name '{0}' not founded in datasource.", boundColumn.FieldName));
                }

                TableHeaderCell cellHeader = new TableHeaderCell() { Text = boundColumn.Header };
                rowHeader.Cells.Add(cellHeader);
            }

            table.Rows.Add(rowHeader);

            foreach (object dataItem in retrievedData)
            {
                row = new TableRow();
                row.TableSection = TableRowSection.TableBody;

                foreach (BoundColumn boundColumn in this.Columns)
                {
                    PropertyDescriptor prop = TypeDescriptor.GetProperties(dataItem).Find(boundColumn.FieldName, false);

                    if (prop == null)
                    {
                        continue;
                    }

                    if (prop.GetValue(dataItem) == null)
                    {
                        row.Cells.Add(new TableCell());
                        continue;
                    }

                    switch (boundColumn.GetType().FullName)
                    {
                        case "NewLife.Bootstrap.Controls.HyperlinkColumn":
                            row.Cells.Add(CreateHyperlinkColumn(prop, dataItem, (HyperlinkColumn)boundColumn));
                            break;

                        case "NewLife.Bootstrap.Controls.DateColumn":
                            row.Cells.Add(CreateDateColumn(prop, dataItem, (DateColumn)boundColumn));
                            break;

                        case "NewLife.Bootstrap.Controls.CheckBoxColumn":
                            row.Cells.Add(CreateCheckBoxColumn(prop, dataItem, (CheckBoxColumn)boundColumn));
                            break;

                        default:
                            row.Cells.Add(CreateColumn(prop, dataItem, boundColumn));
                            break;
                    }
                }

                table.Rows.Add(row);
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> object that contains the event data.</param>
        protected override void OnInit(System.EventArgs e)
        {
            base.OnInit(e);

            // Initialize all child controls.
            this.CreateChildControls();
            this.ChildControlsCreated = true;
        }

        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            this.AddCssClass(this.CssClass);
            this.AddCssClass("table");

            if (this.Zebra == true) this.AddCssClass("table-striped");
            if (this.Condensed == true) this.AddCssClass("table-condensed");

            table.ID = this.ID;
            table.CssClass = this.sCssClass;

            var footer = new Control();
            this.Footer.InstantiateIn(footer);

            this.Controls.Clear();
            this.Controls.Add(table);
            this.Controls.Add(footer);
        }

        /// <summary>
        /// Notifies the server control that an element, either XML or HTML, was parsed, and adds the element to the server control's <see cref="T:System.Web.UI.ControlCollection" /> object.
        /// </summary>
        /// <param name="obj">An <see cref="T:System.Object" /> that represents the parsed element.</param>
        protected override void AddParsedSubObject(object obj)
        {
            if (obj is BoundColumn)
            {
                Columns.Add((BoundColumn)obj);
                return;
            }
        }

        #region Create Columns methods

        /// <summary>
        /// Creates the column.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <param name="dataItem">The data item.</param>
        /// <param name="column">The column.</param>
        /// <returns></returns>
        private TableCell CreateColumn(PropertyDescriptor prop, object dataItem, BoundColumn column)
        {
            TableCell cell = new TableCell() { Text = prop.GetValue(dataItem).ToString() };

            if (column.Width.HasValue)
            {
                cell.Width = column.Width.Value;
            }

            return cell;
        }

        /// <summary>
        /// Creates the check box column.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <param name="dataItem">The data item.</param>
        /// <param name="column">The column.</param>
        /// <returns></returns>
        private TableCell CreateCheckBoxColumn(PropertyDescriptor prop, object dataItem, CheckBoxColumn column)
        {
            TableCell cell = new TableCell();

            CheckBox checkBox = new CheckBox() { Text = "" };
            checkBox.Checked = (bool)prop.GetValue(dataItem);
            cell.Controls.Add(checkBox);

            if (column.Width.HasValue)
            {
                cell.Width = column.Width.Value;
            }

            return cell;
        }

        /// <summary>
        /// Creates the date column.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <param name="dataItem">The data item.</param>
        /// <param name="column">The column.</param>
        /// <returns></returns>
        private TableCell CreateDateColumn(PropertyDescriptor prop, object dataItem, DateColumn column)
        {
            TableCell cell = new TableCell() { Text = String.Format(column.DateFormatString, prop.GetValue(dataItem).ToString()) };

            if (column.Width.HasValue)
            {
                cell.Width = column.Width.Value;
            }

            return cell;
        }

        /// <summary>
        /// Creates the hyperlink column.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <param name="dataItem">The data item.</param>
        /// <param name="column">The column.</param>
        /// <returns></returns>
        private TableCell CreateHyperlinkColumn(PropertyDescriptor prop, object dataItem, HyperlinkColumn column)
        {
            string strNavigationUrl = prop.GetValue(dataItem).ToString();
            strNavigationUrl = String.Format(column.NavigationUrlFormatString, strNavigationUrl);
            strNavigationUrl = this.ResolveClientUrl(strNavigationUrl);

            HyperLink a = new HyperLink() { Text = prop.GetValue(dataItem).ToString() };
            a.NavigateUrl = strNavigationUrl;
            a.Target = column.Target;

            TableCell cell = new TableCell();
            cell.Controls.Add(a);

            if (column.Width.HasValue)
            {
                cell.Width = column.Width.Value;
            }

            return cell;
        }

        #endregion
    }
}