DataBoundControl.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //
  2. // System.Web.UI.WebControls.DataBoundControl
  3. //
  4. // Authors:
  5. // Ben Maurer ([email protected])
  6. // Sanjay Gupta ([email protected])
  7. //
  8. // (C) 2003 Ben Maurer
  9. // (C) 2004 Novell, Inc. (http://www.novell.com)
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. #if NET_2_0
  32. using System.Collections;
  33. using System.Collections.Specialized;
  34. using System.Text;
  35. using System.Web.Util;
  36. using System.ComponentModel;
  37. using System.Security.Permissions;
  38. using System.Web.UI.WebControls.Adapters;
  39. namespace System.Web.UI.WebControls {
  40. // CAS
  41. [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  42. [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  43. // attributes
  44. [DesignerAttribute ("System.Web.UI.Design.WebControls.DataBoundControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
  45. public abstract class DataBoundControl : BaseDataBoundControl
  46. {
  47. DataSourceSelectArguments selectArguments;
  48. DataSourceView currentView;
  49. protected DataBoundControl ()
  50. {
  51. }
  52. /* Used for controls that used to inherit from
  53. * WebControl, so the tag can propagate upwards
  54. */
  55. internal DataBoundControl (HtmlTextWriterTag tag) : base (tag)
  56. {
  57. }
  58. internal IDataSource InternalGetDataSource ()
  59. {
  60. return GetDataSource ();
  61. }
  62. protected virtual IDataSource GetDataSource ()
  63. {
  64. if (IsBoundUsingDataSourceID) {
  65. Control ctrl = FindDataSource ();
  66. if (ctrl == null)
  67. throw new HttpException (string.Format ("A control with ID '{0}' could not be found.", DataSourceID));
  68. if (!(ctrl is IDataSource))
  69. throw new HttpException (string.Format ("The control with ID '{0}' is not a control of type IDataSource.", DataSourceID));
  70. return (IDataSource) ctrl;
  71. }
  72. IDataSource ds = DataSource as IDataSource;
  73. if (ds != null) return ds;
  74. IEnumerable ie = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
  75. return new CollectionDataSource (ie);
  76. }
  77. protected virtual DataSourceView GetData ()
  78. {
  79. if (currentView == null)
  80. UpdateViewData ();
  81. return currentView;
  82. }
  83. DataSourceView InternalGetData ()
  84. {
  85. if (currentView != null)
  86. return currentView;
  87. if (DataSource != null && IsBoundUsingDataSourceID)
  88. throw new HttpException ("Control bound using both DataSourceID and DataSource properties.");
  89. IDataSource ds = GetDataSource ();
  90. if (ds != null)
  91. return ds.GetView (DataMember);
  92. else
  93. return null;
  94. }
  95. protected override void OnDataPropertyChanged ()
  96. {
  97. base.OnDataPropertyChanged ();
  98. currentView = null;
  99. }
  100. protected virtual void OnDataSourceViewChanged (object sender, EventArgs e)
  101. {
  102. RequiresDataBinding = true;
  103. }
  104. // MSDN: The OnPagePreLoad method is overridden by the DataBoundControl class
  105. // to set the BaseDataBoundControl.RequiresDataBinding property to true in
  106. // cases where the HTTP request is a postback and view state is enabled but
  107. // the data-bound control has not yet been bound.
  108. //
  109. // LAMESPEC: RequiresDataBinding is also set when http request is NOT a postback -
  110. // no matter whether view state is enabled. The correct description should be:
  111. //
  112. // The OnPagePreLoad method is override by the DataBoundControl class
  113. // to set the BaseDataBoundControl.RequiresDataBinding property to true in
  114. // cases where the HTTP request is not a postback or it is a postback and view state
  115. // is enabled but the data-bound control has not yet been bound.
  116. protected override void OnPagePreLoad (object sender, EventArgs e)
  117. {
  118. base.OnPagePreLoad (sender, e);
  119. Initialize ();
  120. }
  121. void Initialize ()
  122. {
  123. Page page = Page;
  124. if (page != null) {
  125. // LAMESPEC: see the comment above OnPagePreLoad
  126. if (!page.IsPostBack || (!IsDataBound && IsViewStateEnabled))
  127. RequiresDataBinding = true;
  128. }
  129. }
  130. void UpdateViewData ()
  131. {
  132. if (currentView != null)
  133. currentView.DataSourceViewChanged -= new EventHandler (OnDataSourceViewChanged);
  134. DataSourceView view = InternalGetData ();
  135. if (view != currentView)
  136. currentView = view;
  137. if (currentView != null)
  138. currentView.DataSourceViewChanged += new EventHandler (OnDataSourceViewChanged);
  139. }
  140. protected internal override void OnLoad (EventArgs e)
  141. {
  142. UpdateViewData ();
  143. if (!Initialized) {
  144. Initialize ();
  145. // MSDN: The ConfirmInitState method sets the initialized state of the data-bound
  146. // control. The method is called by the DataBoundControl class in its OnLoad
  147. // method.
  148. ConfirmInitState ();
  149. }
  150. base.OnLoad(e);
  151. }
  152. protected internal virtual void PerformDataBinding (IEnumerable data)
  153. {
  154. }
  155. protected override void ValidateDataSource (object dataSource)
  156. {
  157. if (dataSource == null || dataSource is IListSource || dataSource is IEnumerable || dataSource is IDataSource)
  158. return;
  159. throw new ArgumentException ("Invalid data source source type. The data source must be of type IListSource, IEnumerable or IDataSource.");
  160. }
  161. [ThemeableAttribute (false)]
  162. [DefaultValueAttribute ("")]
  163. [WebCategoryAttribute ("Data")]
  164. public virtual string DataMember {
  165. get { return ViewState.GetString ("DataMember", ""); }
  166. set { ViewState["DataMember"] = value; }
  167. }
  168. [IDReferencePropertyAttribute (typeof(DataSourceControl))]
  169. public override string DataSourceID {
  170. get { return ViewState.GetString ("DataSourceID", ""); }
  171. set {
  172. ViewState ["DataSourceID"] = value;
  173. base.DataSourceID = value;
  174. }
  175. }
  176. //
  177. // See DataBoundControl.MarkAsDataBound msdn doc for the code example
  178. //
  179. protected override void PerformSelect ()
  180. {
  181. // Call OnDataBinding here if bound to a data source using the
  182. // DataSource property (instead of a DataSourceID), because the
  183. // databinding statement is evaluated before the call to GetData.
  184. if (!IsBoundUsingDataSourceID)
  185. OnDataBinding (EventArgs.Empty);
  186. // prevent recursive calls
  187. RequiresDataBinding = false;
  188. SelectArguments = CreateDataSourceSelectArguments ();
  189. GetData ().Select (SelectArguments, new DataSourceViewSelectCallback (OnSelect));
  190. // The PerformDataBinding method has completed.
  191. MarkAsDataBound ();
  192. // Raise the DataBound event.
  193. OnDataBound (EventArgs.Empty);
  194. }
  195. void OnSelect (IEnumerable data)
  196. {
  197. // Call OnDataBinding only if it has not already been
  198. // called in the PerformSelect method.
  199. if (IsBoundUsingDataSourceID) {
  200. OnDataBinding (EventArgs.Empty);
  201. }
  202. // The PerformDataBinding method binds the data in the
  203. // retrievedData collection to elements of the data-bound control.
  204. InternalPerformDataBinding (data);
  205. }
  206. protected void InternalPerformDataBinding (IEnumerable data)
  207. {
  208. DataBoundControlAdapter adapter = Adapter as DataBoundControlAdapter;
  209. if (adapter != null)
  210. adapter.PerformDataBinding (data);
  211. else
  212. PerformDataBinding (data);
  213. }
  214. protected virtual DataSourceSelectArguments CreateDataSourceSelectArguments ()
  215. {
  216. return DataSourceSelectArguments.Empty;
  217. }
  218. protected DataSourceSelectArguments SelectArguments {
  219. get {
  220. if (selectArguments == null)
  221. selectArguments = CreateDataSourceSelectArguments ();
  222. return selectArguments;
  223. }
  224. private set {
  225. selectArguments = value;
  226. }
  227. }
  228. bool IsDataBound {
  229. get {
  230. object dataBound = ViewState ["DataBound"];
  231. return dataBound != null ? (bool) dataBound : false;
  232. }
  233. set {
  234. ViewState ["DataBound"] = value;
  235. }
  236. }
  237. protected void MarkAsDataBound ()
  238. {
  239. IsDataBound = true;
  240. }
  241. }
  242. }
  243. #endif