// // System.Web.UI.WebControls.DetailsView.cs // // Authors: // Lluis Sanchez Gual (lluis@novell.com) // // (C) 2005-2010 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Web.UI; using System.Security.Permissions; using System.Text; using System.IO; using System.Reflection; namespace System.Web.UI.WebControls { [SupportsEventValidation] [ToolboxDataAttribute ("<{0}:DetailsView runat=\"server\" Width=\"125px\" Height=\"50px\">")] [DesignerAttribute ("System.Web.UI.Design.WebControls.DetailsViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] [ControlValuePropertyAttribute ("SelectedValue")] [DefaultEventAttribute ("PageIndexChanging")] [DataKeyProperty ("DataKey")] [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] public class DetailsView: CompositeDataBoundControl, ICallbackEventHandler, ICallbackContainer, IDataItemContainer, INamingContainer, IPostBackEventHandler, IPostBackContainer , IDataBoundItemControl, IDataBoundControl, IFieldControl { object dataItem; Table table; DetailsViewRowCollection rows; DetailsViewRow headerRow; DetailsViewRow footerRow; DetailsViewRow bottomPagerRow; DetailsViewRow topPagerRow; IOrderedDictionary currentEditRowKeys; IOrderedDictionary currentEditNewValues; IOrderedDictionary currentEditOldValues; ITemplate pagerTemplate; ITemplate emptyDataTemplate; ITemplate headerTemplate; ITemplate footerTemplate; PropertyDescriptor[] cachedKeyProperties; readonly string[] emptyKeys = new string[0]; readonly string unhandledEventExceptionMessage = "The DetailsView '{0}' fired event {1} which wasn't handled."; // View state DataControlFieldCollection columns; PagerSettings pagerSettings; TableItemStyle alternatingRowStyle; TableItemStyle editRowStyle; TableItemStyle insertRowStyle; TableItemStyle emptyDataRowStyle; TableItemStyle footerStyle; TableItemStyle headerStyle; TableItemStyle pagerStyle; TableItemStyle rowStyle; TableItemStyle commandRowStyle; TableItemStyle fieldHeaderStyle; IOrderedDictionary _keyTable; DataKey key; DataKey oldEditValues; AutoGeneratedFieldProperties[] autoFieldProperties; static readonly object PageIndexChangedEvent = new object(); static readonly object PageIndexChangingEvent = new object(); static readonly object ItemCommandEvent = new object(); static readonly object ItemCreatedEvent = new object(); static readonly object ItemDeletedEvent = new object(); static readonly object ItemDeletingEvent = new object(); static readonly object ItemInsertedEvent = new object(); static readonly object ItemInsertingEvent = new object(); static readonly object ModeChangingEvent = new object(); static readonly object ModeChangedEvent = new object(); static readonly object ItemUpdatedEvent = new object(); static readonly object ItemUpdatingEvent = new object(); // Control state int pageIndex; DetailsViewMode currentMode = DetailsViewMode.ReadOnly; bool hasCurrentMode; int pageCount; public DetailsView () { rows = new DetailsViewRowCollection (new ArrayList ()); } public event EventHandler PageIndexChanged { add { Events.AddHandler (PageIndexChangedEvent, value); } remove { Events.RemoveHandler (PageIndexChangedEvent, value); } } public event DetailsViewPageEventHandler PageIndexChanging { add { Events.AddHandler (PageIndexChangingEvent, value); } remove { Events.RemoveHandler (PageIndexChangingEvent, value); } } public event DetailsViewCommandEventHandler ItemCommand { add { Events.AddHandler (ItemCommandEvent, value); } remove { Events.RemoveHandler (ItemCommandEvent, value); } } public event EventHandler ItemCreated { add { Events.AddHandler (ItemCreatedEvent, value); } remove { Events.RemoveHandler (ItemCreatedEvent, value); } } public event DetailsViewDeletedEventHandler ItemDeleted { add { Events.AddHandler (ItemDeletedEvent, value); } remove { Events.RemoveHandler (ItemDeletedEvent, value); } } public event DetailsViewDeleteEventHandler ItemDeleting { add { Events.AddHandler (ItemDeletingEvent, value); } remove { Events.RemoveHandler (ItemDeletingEvent, value); } } public event DetailsViewInsertedEventHandler ItemInserted { add { Events.AddHandler (ItemInsertedEvent, value); } remove { Events.RemoveHandler (ItemInsertedEvent, value); } } public event DetailsViewInsertEventHandler ItemInserting { add { Events.AddHandler (ItemInsertingEvent, value); } remove { Events.RemoveHandler (ItemInsertingEvent, value); } } public event DetailsViewModeEventHandler ModeChanging { add { Events.AddHandler (ModeChangingEvent, value); } remove { Events.RemoveHandler (ModeChangingEvent, value); } } public event EventHandler ModeChanged { add { Events.AddHandler (ModeChangedEvent, value); } remove { Events.RemoveHandler (ModeChangedEvent, value); } } public event DetailsViewUpdatedEventHandler ItemUpdated { add { Events.AddHandler (ItemUpdatedEvent, value); } remove { Events.RemoveHandler (ItemUpdatedEvent, value); } } public event DetailsViewUpdateEventHandler ItemUpdating { add { Events.AddHandler (ItemUpdatingEvent, value); } remove { Events.RemoveHandler (ItemUpdatingEvent, value); } } protected virtual void OnPageIndexChanged (EventArgs e) { if (Events != null) { EventHandler eh = (EventHandler) Events [PageIndexChangedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnPageIndexChanging (DetailsViewPageEventArgs e) { if (Events != null) { DetailsViewPageEventHandler eh = (DetailsViewPageEventHandler) Events [PageIndexChangingEvent]; if (eh != null) { eh (this, e); return; } } if (!IsBoundUsingDataSourceID) throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "PageIndexChanging")); } protected virtual void OnItemCommand (DetailsViewCommandEventArgs e) { if (Events != null) { DetailsViewCommandEventHandler eh = (DetailsViewCommandEventHandler) Events [ItemCommandEvent]; if (eh != null) eh (this, e); } } protected virtual void OnItemCreated (EventArgs e) { if (Events != null) { EventHandler eh = (EventHandler) Events [ItemCreatedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnItemDeleted (DetailsViewDeletedEventArgs e) { if (Events != null) { DetailsViewDeletedEventHandler eh = (DetailsViewDeletedEventHandler) Events [ItemDeletedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnItemInserted (DetailsViewInsertedEventArgs e) { if (Events != null) { DetailsViewInsertedEventHandler eh = (DetailsViewInsertedEventHandler) Events [ItemInsertedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnItemInserting (DetailsViewInsertEventArgs e) { if (Events != null) { DetailsViewInsertEventHandler eh = (DetailsViewInsertEventHandler) Events [ItemInsertingEvent]; if (eh != null) { eh (this, e); return; } } if (!IsBoundUsingDataSourceID) throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ItemInserting")); } protected virtual void OnItemDeleting (DetailsViewDeleteEventArgs e) { if (Events != null) { DetailsViewDeleteEventHandler eh = (DetailsViewDeleteEventHandler) Events [ItemDeletingEvent]; if (eh != null) { eh (this, e); return; } } if (!IsBoundUsingDataSourceID) throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ItemDeleting")); } protected virtual void OnModeChanged (EventArgs e) { if (Events != null) { EventHandler eh = (EventHandler) Events [ModeChangedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnModeChanging (DetailsViewModeEventArgs e) { if (Events != null) { DetailsViewModeEventHandler eh = (DetailsViewModeEventHandler) Events [ModeChangingEvent]; if (eh != null) { eh (this, e); return; } } if (!IsBoundUsingDataSourceID) throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ModeChanging")); } protected virtual void OnItemUpdated (DetailsViewUpdatedEventArgs e) { if (Events != null) { DetailsViewUpdatedEventHandler eh = (DetailsViewUpdatedEventHandler) Events [ItemUpdatedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnItemUpdating (DetailsViewUpdateEventArgs e) { if (Events != null) { DetailsViewUpdateEventHandler eh = (DetailsViewUpdateEventHandler) Events [ItemUpdatingEvent]; if (eh != null) { eh (this, e); return; } } if (!IsBoundUsingDataSourceID) throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ItemUpdating")); } DataBoundControlMode IDataBoundItemControl.Mode { get { switch (CurrentMode) { case DetailsViewMode.ReadOnly: return DataBoundControlMode.ReadOnly; case DetailsViewMode.Edit: return DataBoundControlMode.Edit; case DetailsViewMode.Insert: return DataBoundControlMode.Insert; default: throw new InvalidOperationException (String.Format ("Unsupported CurrentMode value '{0}'", CurrentMode)); } } } IDataSource IDataBoundControl.DataSourceObject { get { return base.DataSourceObject; } } IAutoFieldGenerator IFieldControl.FieldsGenerator { get { throw new NotImplementedException (); } set { throw new NotImplementedException (); } } [WebCategoryAttribute ("Paging")] [DefaultValueAttribute (false)] public virtual bool AllowPaging { get { object ob = ViewState ["AllowPaging"]; if (ob != null) return (bool) ob; return false; } set { ViewState ["AllowPaging"] = value; RequireBinding (); } } [DefaultValueAttribute (null)] [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TableItemStyle AlternatingRowStyle { get { if (alternatingRowStyle == null) { alternatingRowStyle = new TableItemStyle (); if (IsTrackingViewState) alternatingRowStyle.TrackViewState(); } return alternatingRowStyle; } } [WebCategoryAttribute ("Behavior")] [DefaultValueAttribute (false)] public virtual bool AutoGenerateEditButton { get { object ob = ViewState ["AutoGenerateEditButton"]; if (ob != null) return (bool) ob; return false; } set { ViewState ["AutoGenerateEditButton"] = value; RequireBinding (); } } [WebCategoryAttribute ("Behavior")] [DefaultValueAttribute (false)] public virtual bool AutoGenerateDeleteButton { get { object ob = ViewState ["AutoGenerateDeleteButton"]; if (ob != null) return (bool) ob; return false; } set { ViewState ["AutoGenerateDeleteButton"] = value; RequireBinding (); } } [WebCategoryAttribute ("Behavior")] [DefaultValueAttribute (false)] public virtual bool AutoGenerateInsertButton { get { object ob = ViewState ["AutoGenerateInsertButton"]; if (ob != null) return (bool) ob; return false; } set { ViewState ["AutoGenerateInsertButton"] = value; RequireBinding (); } } [WebCategoryAttribute ("Behavior")] [DefaultValueAttribute (true)] public virtual bool AutoGenerateRows { get { object ob = ViewState ["AutoGenerateRows"]; if (ob != null) return (bool) ob; return true; } set { ViewState ["AutoGenerateRows"] = value; RequireBinding (); } } [UrlPropertyAttribute] [WebCategoryAttribute ("Appearance")] [DefaultValueAttribute ("")] [EditorAttribute ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] public virtual string BackImageUrl { get { if (ControlStyleCreated) return ((TableStyle) ControlStyle).BackImageUrl; return String.Empty; } set { ((TableStyle) ControlStyle).BackImageUrl = value; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual DetailsViewRow BottomPagerRow { get { EnsureChildControls (); return bottomPagerRow; } } [WebCategoryAttribute ("Accessibility")] [DefaultValueAttribute ("")] [LocalizableAttribute (true)] public virtual string Caption { get { object ob = ViewState ["Caption"]; if (ob != null) return (string) ob; return String.Empty; } set { ViewState ["Caption"] = value; RequireBinding (); } } [WebCategoryAttribute ("Accessibility")] [DefaultValueAttribute (TableCaptionAlign.NotSet)] public virtual TableCaptionAlign CaptionAlign { get { object o = ViewState ["CaptionAlign"]; if(o != null) return (TableCaptionAlign) o; return TableCaptionAlign.NotSet; } set { ViewState ["CaptionAlign"] = value; RequireBinding (); } } [WebCategoryAttribute ("Layout")] [DefaultValueAttribute (-1)] public virtual int CellPadding { get { if (ControlStyleCreated) return ((TableStyle) ControlStyle).CellPadding; return -1; } set { ((TableStyle) ControlStyle).CellPadding = value; } } [WebCategoryAttribute ("Layout")] [DefaultValueAttribute (0)] public virtual int CellSpacing { get { if (ControlStyleCreated) return ((TableStyle) ControlStyle).CellSpacing; return 0; } set { ((TableStyle) ControlStyle).CellSpacing = value; } } [DefaultValueAttribute (null)] [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TableItemStyle CommandRowStyle { get { if (commandRowStyle == null) { commandRowStyle = new TableItemStyle (); if (IsTrackingViewState) commandRowStyle.TrackViewState(); } return commandRowStyle; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public DetailsViewMode CurrentMode { get { return hasCurrentMode ? currentMode : DefaultMode; } private set { hasCurrentMode = true; currentMode = value; } } DetailsViewMode defaultMode = DetailsViewMode.ReadOnly; [DefaultValueAttribute (DetailsViewMode.ReadOnly)] [WebCategoryAttribute ("Behavior")] public virtual DetailsViewMode DefaultMode { get { return defaultMode; } set { defaultMode = value; RequireBinding (); } } [EditorAttribute ("System.Web.UI.Design.WebControls.DataControlFieldTypeEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] [MergablePropertyAttribute (false)] [PersistenceModeAttribute (PersistenceMode.InnerProperty)] [DefaultValueAttribute (null)] [WebCategoryAttribute ("Misc")] public virtual DataControlFieldCollection Fields { get { if (columns == null) { columns = new DataControlFieldCollection (); columns.FieldsChanged += new EventHandler (OnFieldsChanged); if (IsTrackingViewState) ((IStateManager)columns).TrackViewState (); } return columns; } } string[] dataKeyNames = null; [DefaultValueAttribute (null)] [WebCategoryAttribute ("Data")] [TypeConverter (typeof(StringArrayConverter))] [EditorAttribute ("System.Web.UI.Design.WebControls.DataFieldEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] public virtual string[] DataKeyNames { get { if (dataKeyNames == null) return emptyKeys; else return dataKeyNames; } set { dataKeyNames = value; RequireBinding (); } } IOrderedDictionary KeyTable { get { if (_keyTable == null) _keyTable = new OrderedDictionary (DataKeyNames.Length); return _keyTable; } } [BrowsableAttribute (false)] [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] public virtual DataKey DataKey { get { if (key == null) key = new DataKey (KeyTable); return key; } } DataKey OldEditValues { get { if (oldEditValues == null) oldEditValues = new DataKey (new OrderedDictionary ()); return oldEditValues; } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [DefaultValueAttribute (null)] public TableItemStyle EditRowStyle { get { if (editRowStyle == null) { editRowStyle = new TableItemStyle (); if (IsTrackingViewState) editRowStyle.TrackViewState(); } return editRowStyle; } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [DefaultValueAttribute (null)] public TableItemStyle EmptyDataRowStyle { get { if (emptyDataRowStyle == null) { emptyDataRowStyle = new TableItemStyle (); if (IsTrackingViewState) emptyDataRowStyle.TrackViewState(); } return emptyDataRowStyle; } } [DefaultValue (null)] [TemplateContainer (typeof(DetailsView), BindingDirection.OneWay)] [PersistenceMode (PersistenceMode.InnerProperty)] [Browsable (false)] public virtual ITemplate EmptyDataTemplate { get { return emptyDataTemplate; } set { emptyDataTemplate = value; } } [LocalizableAttribute (true)] [WebCategoryAttribute ("Appearance")] [DefaultValueAttribute ("")] public virtual string EmptyDataText { get { object ob = ViewState ["EmptyDataText"]; if (ob != null) return (string) ob; return String.Empty; } set { ViewState ["EmptyDataText"] = value; RequireBinding (); } } [WebCategoryAttribute ("Behavior")] [DefaultValueAttribute (false)] public virtual bool EnablePagingCallbacks { get { object ob = ViewState ["EnablePagingCallbacks"]; if (ob != null) return (bool) ob; return false; } set { ViewState ["EnablePagingCallbacks"] = value; RequireBinding (); } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TableItemStyle FieldHeaderStyle { get { if (fieldHeaderStyle == null) { fieldHeaderStyle = new TableItemStyle (); if (IsTrackingViewState) fieldHeaderStyle.TrackViewState(); } return fieldHeaderStyle; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual DetailsViewRow FooterRow { get { EnsureChildControls (); return footerRow; } } [DefaultValue (null)] [TemplateContainer (typeof(DetailsView), BindingDirection.OneWay)] [PersistenceMode (PersistenceMode.InnerProperty)] [Browsable (false)] public virtual ITemplate FooterTemplate { get { return footerTemplate; } set { footerTemplate = value; } } [LocalizableAttribute (true)] [WebCategoryAttribute ("Appearance")] [DefaultValueAttribute ("")] public virtual string FooterText { get { object ob = ViewState ["FooterText"]; if (ob != null) return (string) ob; return String.Empty; } set { ViewState ["FooterText"] = value; RequireBinding (); } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TableItemStyle FooterStyle { get { if (footerStyle == null) { footerStyle = new TableItemStyle (); if (IsTrackingViewState) footerStyle.TrackViewState(); } return footerStyle; } } [WebCategoryAttribute ("Appearance")] [DefaultValueAttribute (GridLines.Both)] public virtual GridLines GridLines { get { if (ControlStyleCreated) return ((TableStyle) ControlStyle).GridLines; return GridLines.Both; } set { ((TableStyle) ControlStyle).GridLines = value; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual DetailsViewRow HeaderRow { get { EnsureChildControls (); return headerRow; } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TableItemStyle HeaderStyle { get { if (headerStyle == null) { headerStyle = new TableItemStyle (); if (IsTrackingViewState) headerStyle.TrackViewState(); } return headerStyle; } } [DefaultValue (null)] [TemplateContainer (typeof(DetailsView), BindingDirection.OneWay)] [PersistenceMode (PersistenceMode.InnerProperty)] [Browsable (false)] public virtual ITemplate HeaderTemplate { get { return headerTemplate; } set { headerTemplate = value; } } [LocalizableAttribute (true)] [WebCategoryAttribute ("Appearance")] [DefaultValueAttribute ("")] public virtual string HeaderText { get { object ob = ViewState ["HeaderText"]; if (ob != null) return (string) ob; return String.Empty; } set { ViewState ["HeaderText"] = value; RequireBinding (); } } [Category ("Layout")] [DefaultValueAttribute (HorizontalAlign.NotSet)] public virtual HorizontalAlign HorizontalAlign { get { if (ControlStyleCreated) return ((TableStyle) ControlStyle).HorizontalAlign; return HorizontalAlign.NotSet; } set { ((TableStyle) ControlStyle).HorizontalAlign = value; } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [DefaultValueAttribute (null)] public TableItemStyle InsertRowStyle { get { if (insertRowStyle == null) { insertRowStyle = new TableItemStyle (); if (IsTrackingViewState) insertRowStyle.TrackViewState(); } return insertRowStyle; } } [BrowsableAttribute (false)] [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] public virtual int PageCount { get { return pageCount; } private set { pageCount = value; } } [WebCategoryAttribute ("Paging")] [BindableAttribute (true, BindingDirection.OneWay)] [DefaultValueAttribute (0)] public virtual int PageIndex { get { if (CurrentMode == DetailsViewMode.Insert) return -1; return pageIndex; } set { if (value < -1) throw new ArgumentOutOfRangeException ("PageIndex must be non-negative"); if (pageIndex == value || value == -1) return; pageIndex = value; RequireBinding (); } } [WebCategoryAttribute ("Paging")] [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)] [NotifyParentPropertyAttribute (true)] [PersistenceModeAttribute (PersistenceMode.InnerProperty)] public virtual PagerSettings PagerSettings { get { if (pagerSettings == null) { pagerSettings = new PagerSettings (this); if (IsTrackingViewState) ((IStateManager)pagerSettings).TrackViewState (); } return pagerSettings; } } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TableItemStyle PagerStyle { get { if (pagerStyle == null) { pagerStyle = new TableItemStyle (); if (IsTrackingViewState) pagerStyle.TrackViewState(); } return pagerStyle; } } [DefaultValue (null)] [TemplateContainer (typeof (DetailsView), BindingDirection.OneWay)] [PersistenceMode (PersistenceMode.InnerProperty)] [Browsable (false)] public virtual ITemplate PagerTemplate { get { return pagerTemplate; } set { pagerTemplate = value; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual DetailsViewRowCollection Rows { get { EnsureChildControls (); return rows; } } [BrowsableAttribute(false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public IAutoFieldGenerator RowsGenerator { get; set; } [WebCategoryAttribute ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [DefaultValue (null)] public TableItemStyle RowStyle { get { if (rowStyle == null) { rowStyle = new TableItemStyle (); if (IsTrackingViewState) rowStyle.TrackViewState(); } return rowStyle; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public object SelectedValue { get { return DataKey.Value; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual DetailsViewRow TopPagerRow { get { EnsureChildControls (); return topPagerRow; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual object DataItem { get { return dataItem; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public int DataItemCount { get { return PageCount; } } [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)] [BrowsableAttribute (false)] public virtual int DataItemIndex { get { return PageIndex; } } int IDataItemContainer.DisplayIndex { get { return PageIndex; } } int IDataItemContainer.DataItemIndex { get { return DataItemIndex; } } [MonoTODO ("Make use of it in the code")] [DefaultValue (true)] public virtual bool EnableModelValidation { get; set; } public virtual bool IsBindableType (Type type) { return type.IsPrimitive || type == typeof (string) || type == typeof (DateTime) || type == typeof (Guid) || type == typeof (Decimal); } protected override DataSourceSelectArguments CreateDataSourceSelectArguments () { DataSourceSelectArguments arg = new DataSourceSelectArguments (); DataSourceView view = GetData (); if (AllowPaging && view.CanPage) { arg.StartRowIndex = PageIndex; if (view.CanRetrieveTotalRowCount) { arg.RetrieveTotalRowCount = true; arg.MaximumRows = 1; } else arg.MaximumRows = -1; } return arg; } protected virtual ICollection CreateFieldSet (object dataItem, bool useDataSource) { bool autoGenerate = AutoGenerateRows; if (autoGenerate) { IAutoFieldGenerator fieldGenerator = RowsGenerator; if (fieldGenerator != null) return fieldGenerator.GenerateFields (this); } ArrayList fields = new ArrayList (); if (AutoGenerateRows) { if (useDataSource) { if (dataItem != null) fields.AddRange (CreateAutoGeneratedRows (dataItem)); } else { if (autoFieldProperties != null) { foreach (AutoGeneratedFieldProperties props in autoFieldProperties) fields.Add (CreateAutoGeneratedRow (props)); } } } fields.AddRange (Fields); if (AutoGenerateEditButton || AutoGenerateDeleteButton || AutoGenerateInsertButton) { CommandField field = new CommandField (); field.ShowEditButton = AutoGenerateEditButton; field.ShowDeleteButton = AutoGenerateDeleteButton; field.ShowInsertButton = AutoGenerateInsertButton; fields.Add (field); } return fields; } protected virtual ICollection CreateAutoGeneratedRows (object dataItem) { if (dataItem == null) return null; ArrayList list = new ArrayList (); autoFieldProperties = CreateAutoFieldProperties (dataItem); foreach (AutoGeneratedFieldProperties props in autoFieldProperties) list.Add (CreateAutoGeneratedRow (props)); return list; } protected virtual AutoGeneratedField CreateAutoGeneratedRow (AutoGeneratedFieldProperties fieldProperties) { return new AutoGeneratedField (fieldProperties); } AutoGeneratedFieldProperties[] CreateAutoFieldProperties (object dataItem) { if (IsBindableType (dataItem.GetType ())) { AutoGeneratedFieldProperties field = new AutoGeneratedFieldProperties (); ((IStateManager) field).TrackViewState (); field.Name = "Item"; field.DataField = BoundField.ThisExpression; field.Type = dataItem.GetType (); return new AutoGeneratedFieldProperties [] { field }; } PropertyDescriptorCollection props = TypeDescriptor.GetProperties (dataItem, false); if (props != null && props.Count > 0) { ArrayList retVal = new ArrayList (); foreach (PropertyDescriptor current in props) { if (IsBindableType (current.PropertyType)) { AutoGeneratedFieldProperties field = new AutoGeneratedFieldProperties (); ((IStateManager) field).TrackViewState (); field.Name = current.Name; field.DataField = current.Name; for (int i = 0; i < DataKeyNames.Length; i++) { if (string.Compare (DataKeyNames [i], current.Name, StringComparison.InvariantCultureIgnoreCase) == 0) { field.IsReadOnly = true; break; } } field.Type = current.PropertyType; retVal.Add (field); } } if (retVal.Count > 0) return (AutoGeneratedFieldProperties []) retVal.ToArray (typeof (AutoGeneratedFieldProperties)); } throw new HttpException (String.Format ("DetailsView with id '{0}' did not have any properties or attributes from which to generate fields. Ensure that your data source has content.", ID)); } protected virtual DetailsViewRow CreateRow (int rowIndex, DataControlRowType rowType, DataControlRowState rowState) { DetailsViewRow row; if (rowType == DataControlRowType.Pager) row = new DetailsViewPagerRow (rowIndex, rowType, rowState); else row = new DetailsViewRow (rowIndex, rowType, rowState); return row; } void RequireBinding () { if (Initialized) RequiresDataBinding = true; } protected virtual Table CreateTable () { return new ContainedTable (this); } protected override Style CreateControlStyle () { TableStyle style = new TableStyle (); style.GridLines = GridLines.Both; style.CellSpacing = 0; return style; } protected override int CreateChildControls (IEnumerable dataSource, bool dataBinding) { PagedDataSource pagedDataSource = new PagedDataSource (); pagedDataSource.DataSource = CurrentMode != DetailsViewMode.Insert ? dataSource : null; pagedDataSource.AllowPaging = AllowPaging; pagedDataSource.PageSize = 1; pagedDataSource.CurrentPageIndex = PageIndex; if (dataBinding && CurrentMode != DetailsViewMode.Insert) { DataSourceView view = GetData (); if (view != null && view.CanPage) { pagedDataSource.AllowServerPaging = true; if (SelectArguments.RetrieveTotalRowCount) pagedDataSource.VirtualCount = SelectArguments.TotalRowCount; } } bool showPager = AllowPaging && (pagedDataSource.PageCount > 1); Controls.Clear (); table = CreateTable (); Controls.Add (table); headerRow = null; footerRow = null; topPagerRow = null; bottomPagerRow = null; ArrayList list = new ArrayList (); // Gets the current data item if (AllowPaging) { PageCount = pagedDataSource.DataSourceCount; if (PageIndex >= PageCount && PageCount > 0) pageIndex = pagedDataSource.CurrentPageIndex = PageCount - 1; if (pagedDataSource.DataSource != null) { IEnumerator e = pagedDataSource.GetEnumerator (); if (e.MoveNext ()) dataItem = e.Current; } } else { int page = 0; object lastItem = null; if (pagedDataSource.DataSource != null) { IEnumerator e = pagedDataSource.GetEnumerator (); for (; e.MoveNext (); page++) { lastItem = e.Current; if (page == PageIndex) dataItem = e.Current; } } PageCount = page; if (PageIndex >= PageCount && PageCount > 0) { pageIndex = PageCount - 1; dataItem = lastItem; } } if (PageCount == 0 && CurrentMode != DetailsViewMode.Insert) { DetailsViewRow row = CreateEmptyRow (); if (row != null) { table.Rows.Add (row); list.Add (row); } } else { // Creates the set of fields to show ICollection fieldCollection = CreateFieldSet (dataItem, dataBinding && dataItem != null); DataControlField [] fields = new DataControlField [fieldCollection.Count]; fieldCollection.CopyTo (fields, 0); foreach (DataControlField field in fields) { field.Initialize (false, this); if (EnablePagingCallbacks) field.ValidateSupportsCallback (); } // Main table creation headerRow = CreateRow (-1, DataControlRowType.Header, DataControlRowState.Normal); DataControlFieldCell headerCell = new DataControlFieldCell (null); headerCell.ColumnSpan = 2; if (headerTemplate != null) headerTemplate.InstantiateIn (headerCell); else if (!String.IsNullOrEmpty (HeaderText)) headerCell.Text = HeaderText; else headerRow.Visible = false; headerRow.Cells.Add (headerCell); table.Rows.Add (headerRow); if (showPager && PagerSettings.Position == PagerPosition.Top || PagerSettings.Position == PagerPosition.TopAndBottom) { topPagerRow = CreateRow (-1, DataControlRowType.Pager, DataControlRowState.Normal); InitializePager (topPagerRow, pagedDataSource); table.Rows.Add (topPagerRow); } foreach (DataControlField field in fields) { DataControlRowState rstate = GetRowState (list.Count); DetailsViewRow row = CreateRow (PageIndex, DataControlRowType.DataRow, rstate); InitializeRow (row, field); table.Rows.Add (row); list.Add (row); } footerRow = CreateRow (-1, DataControlRowType.Footer, DataControlRowState.Normal); DataControlFieldCell footerCell = new DataControlFieldCell (null); footerCell.ColumnSpan = 2; if (footerTemplate != null) footerTemplate.InstantiateIn (footerCell); else if (!String.IsNullOrEmpty (FooterText)) footerCell.Text = FooterText; else footerRow.Visible = false; footerRow.Cells.Add (footerCell); table.Rows.Add (footerRow); if (showPager && PagerSettings.Position == PagerPosition.Bottom || PagerSettings.Position == PagerPosition.TopAndBottom) { bottomPagerRow = CreateRow (-1, DataControlRowType.Pager, DataControlRowState.Normal); InitializePager (bottomPagerRow, pagedDataSource); table.Rows.Add (bottomPagerRow); } } rows = new DetailsViewRowCollection (list); if (dataBinding) DataBind (false); OnItemCreated (EventArgs.Empty); return PageCount; } protected override void EnsureDataBound () { if (CurrentMode == DetailsViewMode.Insert) { if (RequiresDataBinding) { OnDataBinding (EventArgs.Empty); RequiresDataBinding = false; InternalPerformDataBinding (null); MarkAsDataBound (); OnDataBound (EventArgs.Empty); } } else base.EnsureDataBound (); } DataControlRowState GetRowState (int index) { DataControlRowState rstate = (index % 2) == 0 ? DataControlRowState.Normal : DataControlRowState.Alternate; if (CurrentMode == DetailsViewMode.Edit) rstate |= DataControlRowState.Edit; else if (CurrentMode == DetailsViewMode.Insert) rstate |= DataControlRowState.Insert; return rstate; } protected virtual void InitializePager (DetailsViewRow row, PagedDataSource pagedDataSource) { TableCell cell = new TableCell (); cell.ColumnSpan = 2; if (pagerTemplate != null) pagerTemplate.InstantiateIn (cell); else cell.Controls.Add (PagerSettings.CreatePagerControl (pagedDataSource.CurrentPageIndex, pagedDataSource.PageCount)); row.Cells.Add (cell); } DetailsViewRow CreateEmptyRow () { TableCell cell = new TableCell (); if (emptyDataTemplate != null) emptyDataTemplate.InstantiateIn (cell); else if (!String.IsNullOrEmpty (EmptyDataText)) cell.Text = EmptyDataText; else return null; DetailsViewRow row = CreateRow (-1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal); row.Cells.Add (cell); return row; } protected virtual void InitializeRow (DetailsViewRow row, DataControlField field) { if (!field.Visible) { row.Visible = false; return; } row.ContainingField = field; DataControlFieldCell cell; if (field.ShowHeader) { cell = new DataControlFieldCell (field); row.Cells.Add (cell); field.InitializeCell (cell, DataControlCellType.Header, row.RowState, row.RowIndex); } cell = new DataControlFieldCell (field); if (!field.ShowHeader) cell.ColumnSpan = 2; row.Cells.Add (cell); field.InitializeCell (cell, DataControlCellType.DataCell, row.RowState, row.RowIndex); if (CurrentMode == DetailsViewMode.Insert && !field.InsertVisible) row.Visible = false; } void FillRowDataKey (object dataItem) { KeyTable.Clear (); if (cachedKeyProperties == null) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties (dataItem); cachedKeyProperties = new PropertyDescriptor [DataKeyNames.Length]; for (int n=0; n 0) SetPageIndex (PageIndex - 1); break; case DataControlCommands.EditCommandName: ProcessChangeMode (DetailsViewMode.Edit); break; case DataControlCommands.NewCommandName: ProcessChangeMode (DetailsViewMode.Insert); break; case DataControlCommands.UpdateCommandName: UpdateItem (param, causesValidation); break; case DataControlCommands.CancelCommandName: CancelEdit (); break; case DataControlCommands.DeleteCommandName: DeleteItem (); break; case DataControlCommands.InsertCommandName: InsertItem (causesValidation); break; } } public void SetPageIndex (int index) { DetailsViewPageEventArgs args = new DetailsViewPageEventArgs (index); OnPageIndexChanging (args); if (args.Cancel || !IsBoundUsingDataSourceID) return; if (args.NewPageIndex < 0 || args.NewPageIndex >= PageCount) return; EndRowEdit (false); PageIndex = args.NewPageIndex; OnPageIndexChanged (EventArgs.Empty); } public void ChangeMode (DetailsViewMode newMode) { CurrentMode = newMode; RequireBinding (); } void ProcessChangeMode (DetailsViewMode newMode) { DetailsViewModeEventArgs args = new DetailsViewModeEventArgs (newMode, false); OnModeChanging (args); if (args.Cancel || !IsBoundUsingDataSourceID) return; ChangeMode (args.NewMode); OnModeChanged (EventArgs.Empty); } void CancelEdit () { DetailsViewModeEventArgs args = new DetailsViewModeEventArgs (DetailsViewMode.ReadOnly, true); OnModeChanging (args); if (args.Cancel || !IsBoundUsingDataSourceID) return; EndRowEdit (); } public virtual void UpdateItem (bool causesValidation) { UpdateItem (null, causesValidation); } void UpdateItem (string param, bool causesValidation) { if (causesValidation && Page != null && !Page.IsValid) return; if (CurrentMode != DetailsViewMode.Edit) throw new HttpException (); currentEditOldValues = OldEditValues.Values; currentEditRowKeys = DataKey.Values; currentEditNewValues = GetRowValues (false, false); DetailsViewUpdateEventArgs args = new DetailsViewUpdateEventArgs (param, currentEditRowKeys, currentEditOldValues, currentEditNewValues); OnItemUpdating (args); if (args.Cancel || !IsBoundUsingDataSourceID) return; DataSourceView view = GetData (); if (view == null) throw new HttpException ("The DataSourceView associated to data bound control was null"); view.Update (currentEditRowKeys, currentEditNewValues, currentEditOldValues, new DataSourceViewOperationCallback (UpdateCallback)); } bool UpdateCallback (int recordsAffected, Exception exception) { DetailsViewUpdatedEventArgs dargs = new DetailsViewUpdatedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditOldValues, currentEditNewValues); OnItemUpdated (dargs); if (!dargs.KeepInEditMode) EndRowEdit (); return dargs.ExceptionHandled; } public virtual void InsertItem (bool causesValidation) { InsertItem (null, causesValidation); } void InsertItem (string param, bool causesValidation) { if (causesValidation && Page != null && !Page.IsValid) return; if (CurrentMode != DetailsViewMode.Insert) throw new HttpException (); currentEditNewValues = GetRowValues (false, true); DetailsViewInsertEventArgs args = new DetailsViewInsertEventArgs (param, currentEditNewValues); OnItemInserting (args); if (args.Cancel || !IsBoundUsingDataSourceID) return; DataSourceView view = GetData (); if (view == null) throw new HttpException ("The DataSourceView associated to data bound control was null"); view.Insert (currentEditNewValues, new DataSourceViewOperationCallback (InsertCallback)); } bool InsertCallback (int recordsAffected, Exception exception) { DetailsViewInsertedEventArgs dargs = new DetailsViewInsertedEventArgs (recordsAffected, exception, currentEditNewValues); OnItemInserted (dargs); if (!dargs.KeepInInsertMode) EndRowEdit (); return dargs.ExceptionHandled; } public virtual void DeleteItem () { currentEditRowKeys = DataKey.Values; currentEditNewValues = GetRowValues (true, false); DetailsViewDeleteEventArgs args = new DetailsViewDeleteEventArgs (PageIndex, currentEditRowKeys, currentEditNewValues); OnItemDeleting (args); if (args.Cancel || !IsBoundUsingDataSourceID) return; DataSourceView view = GetData (); if (view != null) view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback)); else { DetailsViewDeletedEventArgs dargs = new DetailsViewDeletedEventArgs (0, null, currentEditRowKeys, currentEditNewValues); OnItemDeleted (dargs); } if (PageIndex > 0 && PageIndex == PageCount - 1) PageIndex --; RequireBinding (); } bool DeleteCallback (int recordsAffected, Exception exception) { DetailsViewDeletedEventArgs dargs = new DetailsViewDeletedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditNewValues); OnItemDeleted (dargs); return dargs.ExceptionHandled; } void EndRowEdit () { EndRowEdit (true); } void EndRowEdit (bool switchToDefaultMode) { if (switchToDefaultMode) ChangeMode (DefaultMode); oldEditValues = new DataKey (new OrderedDictionary ()); currentEditRowKeys = null; currentEditOldValues = null; currentEditNewValues = null; RequireBinding (); } protected internal override void LoadControlState (object savedState) { if (savedState == null) return; object[] state = (object[]) savedState; base.LoadControlState (state[0]); pageIndex = (int) state[1]; pageCount = (int) state[2]; CurrentMode = (DetailsViewMode) state[3]; dataKeyNames = (string[]) state[4]; defaultMode = (DetailsViewMode) state[5]; if (state [6] != null) ((IStateManager) DataKey).LoadViewState (state [6]); if (state [7] != null) ((IStateManager) OldEditValues).LoadViewState (state [7]); } protected internal override object SaveControlState () { object bstate = base.SaveControlState (); return new object[] { bstate, pageIndex, pageCount, CurrentMode, dataKeyNames, defaultMode, (key == null ? null : ((IStateManager)key).SaveViewState()), (oldEditValues == null ? null : ((IStateManager) oldEditValues).SaveViewState ()) }; } protected override void TrackViewState() { base.TrackViewState(); if (columns != null) ((IStateManager)columns).TrackViewState(); if (pagerSettings != null) ((IStateManager)pagerSettings).TrackViewState(); if (alternatingRowStyle != null) ((IStateManager)alternatingRowStyle).TrackViewState(); if (footerStyle != null) ((IStateManager)footerStyle).TrackViewState(); if (headerStyle != null) ((IStateManager)headerStyle).TrackViewState(); if (pagerStyle != null) ((IStateManager)pagerStyle).TrackViewState(); if (rowStyle != null) ((IStateManager)rowStyle).TrackViewState(); if (editRowStyle != null) ((IStateManager)editRowStyle).TrackViewState(); if (insertRowStyle != null) ((IStateManager)insertRowStyle).TrackViewState(); if (emptyDataRowStyle != null) ((IStateManager)emptyDataRowStyle).TrackViewState(); if (key != null) ((IStateManager)key).TrackViewState(); if (autoFieldProperties != null) { foreach (IStateManager sm in autoFieldProperties) sm.TrackViewState (); } if (ControlStyleCreated) ControlStyle.TrackViewState (); } protected override object SaveViewState() { object[] states = new object [13]; states[0] = base.SaveViewState(); states[1] = (columns == null ? null : ((IStateManager)columns).SaveViewState()); states[2] = (pagerSettings == null ? null : ((IStateManager)pagerSettings).SaveViewState()); states[3] = (alternatingRowStyle == null ? null : ((IStateManager)alternatingRowStyle).SaveViewState()); states[4] = (footerStyle == null ? null : ((IStateManager)footerStyle).SaveViewState()); states[5] = (headerStyle == null ? null : ((IStateManager)headerStyle).SaveViewState()); states[6] = (pagerStyle == null ? null : ((IStateManager)pagerStyle).SaveViewState()); states[7] = (rowStyle == null ? null : ((IStateManager)rowStyle).SaveViewState()); states[8] = (insertRowStyle == null ? null : ((IStateManager)insertRowStyle).SaveViewState()); states[9] = (editRowStyle == null ? null : ((IStateManager)editRowStyle).SaveViewState()); states[10] = (emptyDataRowStyle == null ? null : ((IStateManager)emptyDataRowStyle).SaveViewState()); if (autoFieldProperties != null) { object[] data = new object [autoFieldProperties.Length]; bool allNull = true; for (int n=0; n= 0; i--) { if (states [i] != null) return states; } return null; } protected override void LoadViewState (object savedState) { if (savedState == null) { base.LoadViewState (null); return; } object [] states = (object []) savedState; if (states[11] != null) { object[] data = (object[]) states [11]; autoFieldProperties = new AutoGeneratedFieldProperties [data.Length]; for (int n=0; n