File: BaseDataBoundControl.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (287 lines) | stat: -rw-r--r-- 10,547 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
//------------------------------------------------------------------------------
// <copyright file="BaseDataBoundControl.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

namespace System.Web.UI.WebControls {

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Web.Util;

    /// <summary>
    /// A BaseDataBoundControl is bound to a data source and generates its
    /// user interface (or child control hierarchy typically), by enumerating
    /// the items in the data source it is bound to.
    /// BaseDataBoundControl is an abstract base class that defines the common
    /// characteristics of all controls that use a list as a data source, such as
    /// DataGrid, DataBoundTable, ListBox etc. It encapsulates the logic
    /// of how a data-bound control binds to collections or DataControl instances.
    /// </summary>

    [
    Designer("System.Web.UI.Design.WebControls.BaseDataBoundControlDesigner, " + AssemblyRef.SystemDesign),
    DefaultProperty("DataSourceID")
    ]
    public abstract class BaseDataBoundControl : WebControl {

        private static readonly object EventDataBound = new object();

        private object _dataSource;
        private bool _requiresDataBinding;
        private bool _inited;
        private bool _preRendered;
        private bool _requiresBindToNull;
        private bool _throwOnDataPropertyChange;


        /// <summary>
        /// The data source to bind to. This allows a BaseDataBoundControl to bind
        /// to arbitrary lists of data items.
        /// </summary>
        [
        Bindable(true),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        Themeable(false),
        WebCategory("Data"),
        WebSysDescription(SR.BaseDataBoundControl_DataSource),
        ]
        public virtual object DataSource {
            get {
                return _dataSource;
            }
            set {
                if (value != null) {
                    ValidateDataSource(value);
                }
                _dataSource = value;
                OnDataPropertyChanged();
            }
        }


        /// <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(""),
        Themeable(false),
        WebCategory("Data"),
        WebSysDescription(SR.BaseDataBoundControl_DataSourceID)
        ]
        public virtual string DataSourceID {
            get {
                object o = ViewState["DataSourceID"];
                if (o != null) {
                    return (string)o;
                }
                return String.Empty;
            }
            set {
                if (String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(DataSourceID)) {
                    _requiresBindToNull = true;
                }

                ViewState["DataSourceID"] = value;
                OnDataPropertyChanged();
            }
        }


        protected bool Initialized {
            get {
                return _inited;
            }
        }

        /// <summary>
        /// Returns true if the DataBoundControl uses Select/Update/Delete/Insert Methods for databinding. 
        /// Implementation on BaseDataBoundControl returns false.
        /// Override in child classes which support the above two properties.
        /// </summary>
        protected virtual bool IsUsingModelBinders {
           get {
               return false;
           }
        }

        /// <summary>
        /// This returns true only if the DataBoundControl is using a DataSourceID.
        /// Use the IsDataBindingAutomatic property to determine if the data bound control's data binding is
        /// automatic. The data binding is automatic if the control is using a DataSourceID or if control
        /// uses Select/Update/Delete/Insert Methods for data binding.
        /// </summary>
        protected bool IsBoundUsingDataSourceID {
            get {
                return (DataSourceID.Length > 0);
            }
        }

        /// <summary>
        /// This property is used by FormView/GridView/DetailsView/ListView in the following scenarios.
        /// 1. Perform an auto data bind (Listen to OnDataSourceViewChanged event and set RequiresDataBinding to true)
        /// 2. Calling the data source view operations
        /// 3. Raising exceptions when there is no DataSourceId (i.e., a DataSource is in use) and an event for Data Operation is not handled
        /// 4. Raising the ModeChanged events for DataControls
        /// This property is true if the control is bound using a DataSourceId or when the control participates in Model Binding.
        /// </summary>
        protected internal bool IsDataBindingAutomatic {
            get {
                return IsBoundUsingDataSourceID || IsUsingModelBinders;
            }
        }

        public override bool SupportsDisabledAttribute {
            get {
                return RenderingCompatibility < VersionUtil.Framework40;
            }
        }

        protected bool RequiresDataBinding {
            get {
                return _requiresDataBinding;
            }
            set {
                // if we have to play catch-up here because we've already PreRendered, call EnsureDataBound
                if (value && _preRendered && IsDataBindingAutomatic && Page != null && !Page.IsCallback) {
                    _requiresDataBinding = true;
                    EnsureDataBound();
                }
                else {
                    _requiresDataBinding = value;
                }
            }
        }


        [
        WebCategory("Data"),
        WebSysDescription(SR.BaseDataBoundControl_OnDataBound)
        ]
        public event EventHandler DataBound {
            add {
                Events.AddHandler(EventDataBound, value);
            }
            remove {
                Events.RemoveHandler(EventDataBound, value);
            }
        }

        protected void ConfirmInitState() {
            _inited = true; // do this in OnLoad in case we were added to the page after Page.OnPreLoad
        }


        /// <summary>
        /// Overriden by BaseDataBoundControl to use its properties to determine the real
        /// data source that the control should bind to. It then clears the existing
        /// control hierarchy, and calls CreateChildControls to create a new control
        /// hierarchy based on the resolved data source.
        /// The implementation resolves various data source related properties to
        /// arrive at the appropriate IEnumerable implementation to use as the real
        /// data source.
        /// When resolving data sources, the DataSourceID takes highest precedence.
        /// If DataSourceID is not set, the value of the DataSource property is used.
        /// In this second alternative, DataMember is used to extract the appropriate
        /// list if the control has been handed an IListSource as a data source.
        ///
        /// Data bound controls should override PerformDataBinding instead
        /// of DataBind.  If DataBind if overridden, the OnDataBinding and OnDataBound events will
        /// fire in the wrong order.  However, for backwards compat on ListControl and AdRotator, we 
        /// can't seal this method.  It is sealed on all new BaseDataBoundControl-derived controls.
        /// </summary>
        public override void DataBind() {
            // Don't databind when the control is in the designer but not top-level
            if (DesignMode) {
                IDictionary designModeState = GetDesignModeState();
                if (((designModeState == null) || (designModeState["EnableDesignTimeDataBinding"] == null))
                    && (Site == null)) {
                    return;
                }
            }

            PerformSelect();
        }


        protected virtual void EnsureDataBound() {
            try {
                _throwOnDataPropertyChange = true;
                if (RequiresDataBinding && (IsDataBindingAutomatic || _requiresBindToNull)) {
                    DataBind();
                    _requiresBindToNull = false;
                }
            }
            finally {
                _throwOnDataPropertyChange = false;
            }
        }

        internal void InternalEnsureDataBound() {
            EnsureDataBound();
        }


        protected virtual void OnDataBound(EventArgs e) {
            EventHandler handler = Events[EventDataBound] as EventHandler;
            if (handler != null) {
                handler(this, e);
            }
        }


        /// <devdoc>
        ///  This method is called when DataMember, DataSource, or DataSourceID is changed.
        /// </devdoc>
        protected virtual void OnDataPropertyChanged() {
            if (_throwOnDataPropertyChange) {
                throw new HttpException(SR.GetString(SR.DataBoundControl_InvalidDataPropertyChange, ID));
            }
            if (_inited) {
                RequiresDataBinding = true;
            }
        }


        protected internal override void OnInit(EventArgs e) {
            base.OnInit(e);

            if (Page != null) {
                Page.PreLoad += new EventHandler(this.OnPagePreLoad);
                
                if (!IsViewStateEnabled && Page.IsPostBack) {
                    RequiresDataBinding = true;
                }
            }
        }

        protected virtual void OnPagePreLoad(object sender, EventArgs e) {
            _inited = true;
            if (Page != null) {
                Page.PreLoad -= new EventHandler(this.OnPagePreLoad);
            }
        }


        protected internal override void OnPreRender(EventArgs e) {
            _preRendered = true;
            EnsureDataBound();
            base.OnPreRender(e);
        }
        
        /// <summary>
        /// Override to control how the data is selected and the control is databound.
        /// </summary>
        protected abstract void PerformSelect();


        protected abstract void ValidateDataSource(object dataSource);
    }
}