//
// Authors:
// Ben Maurer (bmaurer@users.sourceforge.net)
+// Sanjay Gupta (gsanjay@novell.com)
//
// (C) 2003 Ben Maurer
+// (C) 2004 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.
//
#if NET_2_0
using System.Text;
using System.Web.Util;
using System.ComponentModel;
+using System.Security.Permissions;
namespace System.Web.UI.WebControls {
- public abstract class DataBoundControl : WebControl
+
+ // CAS
+ [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+ [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+ // attributes
+ [DesignerAttribute ("System.Web.UI.Design.WebControls.DataBoundControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
+ public abstract class DataBoundControl : BaseDataBoundControl
{
- public event EventHandler DataBound;
-
+ DataSourceSelectArguments selectArguments;
+ DataSourceView currentView;
+
protected DataBoundControl ()
{
}
-
- public sealed override void DataBind ()
+
+ /* Used for controls that used to inherit from
+ * WebControl, so the tag can propagate upwards
+ */
+ internal DataBoundControl (HtmlTextWriterTag tag) : base (tag)
{
- PerformDataBinding ();
- RequiresDataBinding = false;
- OnDataBound (EventArgs.Empty);
}
- protected void EnsureDataBound ()
+
+ protected virtual IDataSource GetDataSource ()
{
- if (RequiresDataBinding && DataSourceID != "")
- DataBind ();
- }
+ if (IsBoundUsingDataSourceID) {
+ Control namingContainer;
+ Control ctrl = null;
- protected virtual object GetDataSourceObject()
- {
- if (DataSourceID != "")
- return (IDataSource) NamingContainer.FindControl (DataSourceID);
+ namingContainer = NamingContainer;
+
+ while (namingContainer != null) {
+ ctrl = namingContainer.FindControl (DataSourceID);
+ if (ctrl != null)
+ break;
+ namingContainer = namingContainer.NamingContainer;
+ }
+
+ if (ctrl == null)
+ throw new HttpException (string.Format ("A control with ID '{0}' could not be found.", DataSourceID));
+ if (!(ctrl is IDataSource))
+ throw new HttpException (string.Format ("The control with ID '{0}' is not a control of type IDataSource.", DataSourceID));
+ return (IDataSource) ctrl;
+ }
+
+ if (DataSource == null) return null;
- return DataSource;
+ IDataSource ds = DataSource as IDataSource;
+ if (ds != null) return ds;
+
+ IEnumerable ie = DataSourceHelper.GetResolvedDataSource (DataSource, DataMember);
+ if (ie != null) return new CollectionDataSource (ie);
+
+ throw new HttpException (string.Format ("Unexpected data source type: {0}", DataSource.GetType()));
}
+ protected virtual DataSourceView GetData ()
+ {
+ if (currentView == null)
+ UpdateViewData ();
+ return currentView;
+ }
- protected virtual IEnumerable GetResolvedDataSource ()
+ DataSourceView InternalGetData ()
{
- if (DataSource != null && DataSourceID != "")
- throw new HttpException ();
+ if (DataSource != null && IsBoundUsingDataSourceID)
+ throw new HttpException ("Control bound using both DataSourceID and DataSource properties.");
- IDataSource ds = GetDataSourceObject () as IDataSource;
- if (ds != null && DataSourceID != "")
- return ds.GetView (DataMember).Select ();
- else if (DataSource != null)
- return DataSourceHelper.GetResolvedDataSource (DataSource, DataMember);
+ IDataSource ds = GetDataSource ();
+ if (ds != null)
+ return ds.GetView (DataMember);
else
return null;
}
- protected bool IsBoundToDataSourceControl()
+ protected override void OnDataPropertyChanged ()
{
- return (GetDataSourceObject () is IDataSource) && DataSourceID != "";
+ base.OnDataPropertyChanged ();
+ UpdateViewData ();
}
- protected virtual void OnDataBound(EventArgs e) {
- if (DataBound != null)
- DataBound (this, e);
- }
-
- protected virtual void OnDataPropertyChanged ()
- {
- this.RequiresDataBinding = true;
- }
-
- protected virtual void OnDataSourceChanged (object sender, EventArgs e)
+ protected virtual void OnDataSourceViewChanged (object sender, EventArgs e)
{
RequiresDataBinding = true;
}
- // should be `internal protected' (why, oh WHY did they do that !?!)
- protected override void OnInit (EventArgs e)
+ protected override void OnPagePreLoad (object sender, EventArgs e)
{
- base.OnInit(e);
- inited = true;
- if (!Page.IsPostBack)
- RequiresDataBinding = true;
+ base.OnPagePreLoad (sender, e);
+ UpdateViewData ();
}
- // should be `internal protected' (why, oh WHY did they do that !?!)
- protected override void OnLoad (EventArgs e)
+ void UpdateViewData ()
{
- IDataSource ds = GetDataSourceObject () as IDataSource;
- if (ds != null && DataSourceID != "")
- ds.DataSourceChanged += new EventHandler (OnDataSourceChanged);
-
- base.OnLoad(e);
+ DataSourceView view = InternalGetData ();
+ if (view == currentView) return;
+
+ if (currentView != null)
+ currentView.DataSourceViewChanged -= new EventHandler (OnDataSourceViewChanged);
+
+ currentView = view;
+
+ if (view != null)
+ view.DataSourceViewChanged += new EventHandler (OnDataSourceViewChanged);
}
- // should be `internal protected' (why, oh WHY did they do that !?!)
- protected override void OnPreRender (EventArgs e)
+ protected internal override void OnLoad (EventArgs e)
{
- EnsureDataBound ();
- base.OnPreRender (e);
+ if (!Page.IsPostBack || (IsViewStateEnabled && !IsDataBound))
+ RequiresDataBinding = true;
+
+ base.OnLoad(e);
}
- protected virtual void PerformDataBinding ()
+ protected internal virtual void PerformDataBinding (IEnumerable data)
{
- OnDataBinding(EventArgs.Empty);
}
-
- protected virtual void ValidateDataSource (object dataSource)
+ protected override void ValidateDataSource (object dataSource)
{
- if (dataSource is IListSource || dataSource is IEnumerable)
+ if (dataSource is IListSource || dataSource is IEnumerable || dataSource is IDataSource)
return;
- throw new ArgumentException ();
+ throw new ArgumentException ("Invalid data source source type. The data source must be of type IListSource, IEnumerable or IDataSource.");
}
+ [ThemeableAttribute (false)]
+ [DefaultValueAttribute ("")]
+ [WebCategoryAttribute ("Data")]
+ public virtual string DataMember {
+ get { return ViewState.GetString ("DataMember", ""); }
+ set { ViewState["DataMember"] = value; }
+ }
- public string DataMember
- {
- get {
- object o = ViewState["DataMember"];
- if(o!=null)
- return (string)o;
- return String.Empty;
- }
+ [IDReferencePropertyAttribute (typeof(DataSourceControl))]
+ public override string DataSourceID {
+ get { return ViewState.GetString ("DataSourceID", ""); }
set {
- ViewState["DataMember"] = value;
+ ViewState ["DataSourceID"] = value;
+ base.DataSourceID = value;
}
}
+
+ //
+ // See DataBoundControl.MarkAsDataBound msdn doc for the code example
+ //
+ protected override void PerformSelect ()
+ {
+ // Call OnDataBinding here if bound to a data source using the
+ // DataSource property (instead of a DataSourceID), because the
+ // databinding statement is evaluated before the call to GetData.
+ if (!IsBoundUsingDataSourceID)
+ OnDataBinding (EventArgs.Empty);
- object dataSource;
- public virtual object DataSource
+ DataSourceView view = GetData ();
+ if (view != null) {
+ view.Select (SelectArguments, new DataSourceViewSelectCallback (OnSelect));
+ MarkAsDataBound ();
+ }
+ }
+
+ void OnSelect (IEnumerable data)
{
+ PerformDataBinding (data);
+ OnDataBound (EventArgs.Empty);
+ }
+
+ protected virtual DataSourceSelectArguments CreateDataSourceSelectArguments ()
+ {
+ return DataSourceSelectArguments.Empty;
+ }
+
+ protected DataSourceSelectArguments SelectArguments {
get {
- return dataSource;
- }
- set {
- ValidateDataSource (value);
- dataSource = value;
+ if (selectArguments == null)
+ selectArguments = CreateDataSourceSelectArguments ();
+ return selectArguments;
}
}
-
- public virtual string DataSourceID {
+
+ bool IsDataBound {
get {
- object o = ViewState ["DataSourceID"];
- if (o != null)
- return (string)o;
-
- return String.Empty;
+ object dataBound = ViewState ["DataBound"];
+ return dataBound != null ? (bool) dataBound : false;
}
set {
- if (inited)
- RequiresDataBinding = true;
-
- ViewState ["DataSourceID"] = value;
+ ViewState ["DataBound"] = value;
}
}
-
- bool requiresDataBinding;
- protected bool RequiresDataBinding {
- get { return requiresDataBinding; }
- set { requiresDataBinding = value; }
+
+ protected void MarkAsDataBound ()
+ {
+ IsDataBound = true;
}
-
- protected bool inited;
}
}
#endif