Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Web.DynamicData / DynamicData / DynamicDataManager.cs
1 namespace System.Web.DynamicData {
2     using System;
3     using System.Collections;
4     using System.Collections.Generic;
5     using System.ComponentModel;
6     using System.ComponentModel.DataAnnotations;
7     using System.Diagnostics;
8     using System.Diagnostics.CodeAnalysis;
9     using System.Drawing;
10     using System.Globalization;
11     using System.Security.Permissions;
12     using System.Web.Resources;
13     using System.Web.UI;
14     using System.Web.UI.WebControls;
15     using System.Web.DynamicData.Util;
16     using System.Data.Objects;
17     using IDataBoundControlInterface = System.Web.UI.WebControls.IDataBoundControl;
18
19     /// <summary>
20     /// Adds behavior to certain control to make them work with Dynamic Data 
21     /// </summary>
22     [NonVisualControl()]
23     [ParseChildren(true)]
24     [PersistChildren(false)]
25     [ToolboxBitmap(typeof(DynamicDataManager), "DynamicDataManager.bmp")]
26     [Designer("System.Web.DynamicData.Design.DynamicDataManagerDesigner, " + AssemblyRef.SystemWebDynamicDataDesign)]
27     public class DynamicDataManager : Control {
28         private DataControlReferenceCollection _dataControls;
29         // Key is used as the set of registered data source controls.  Value is ignored.
30         private Dictionary<IDynamicDataSource, object> _dataSources = new Dictionary<IDynamicDataSource, object>();
31
32         /// <summary>
33         /// Causes foreign entities to be loaded as well setting the proper DataLoadOptions.
34         /// Only works with Linq To Sql.
35         /// </summary>
36         [
37         Category("Behavior"),
38         DefaultValue(false),
39         ResourceDescription("DynamicDataManager_AutoLoadForeignKeys")
40         ]
41         public bool AutoLoadForeignKeys {
42             get;
43             set;
44         }
45
46         [
47         Browsable(false),
48         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
49         EditorBrowsable(EditorBrowsableState.Never)
50         ]
51         public override string ClientID {
52             get {
53                 return base.ClientID;
54             }
55         }
56
57         [
58         Browsable(false),
59         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
60         EditorBrowsable(EditorBrowsableState.Never)
61         ]
62         public override ClientIDMode ClientIDMode {
63             get {
64                 return base.ClientIDMode;
65             }
66             set {
67                 throw new NotImplementedException();
68             }
69         }
70
71         [
72         Category("Behavior"),
73         DefaultValue(null),
74         PersistenceMode(PersistenceMode.InnerProperty),
75         MergableProperty(false),
76         ]
77         public DataControlReferenceCollection DataControls {
78             get {
79                 if (_dataControls == null) {
80                     _dataControls = new DataControlReferenceCollection(this);
81                 }
82                 return _dataControls;
83             }
84         }
85
86         /// <summary>
87         /// See base class documentation
88         /// </summary>
89         [
90         Browsable(false),
91         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
92         EditorBrowsable(EditorBrowsableState.Never)
93         ]
94         public override bool Visible {
95             get {
96                 return base.Visible;
97             }
98             set {
99                 throw new NotImplementedException();
100             }
101         }
102
103         /// <summary>
104         /// See base class documentation
105         /// </summary>
106         [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
107         protected override void OnInit(EventArgs e) {
108             base.OnInit(e);
109
110             // Initialize the collection
111             DataControls.Initialize();
112
113             // Subscribe to the Page's Init to register the controls set in the DataControls collection
114             Page.Init += OnPageInit;
115         }
116
117
118         private void OnPageInit(object sender, EventArgs e) {
119             foreach (DataControlReference controlReference in DataControls) {
120                 Control targetControl = Misc.FindControl(this, controlReference.ControlID);
121                 if (targetControl == null) {
122                     throw new InvalidOperationException(
123                         String.Format(CultureInfo.CurrentCulture,
124                         DynamicDataResources.DynamicDataManager_ControlNotFound,
125                         controlReference.ControlID));
126                 }
127
128                 RegisterControl(targetControl);
129             }
130         }
131
132         /// <summary>
133         /// See base class documentation
134         /// </summary>
135         [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
136         protected override void OnLoad(EventArgs e) {
137             base.OnLoad(e);
138
139             // Go through all the registered data sources
140             foreach (IDynamicDataSource dataSource in _dataSources.Keys) {
141
142                 // Expand any dynamic where parameters that they may use
143                 dataSource.ExpandDynamicWhereParameters();
144             }
145         }
146
147         /// <summary>
148         /// Register a data control to give it Dynamic Data behavior
149         /// </summary>
150         /// <param name="control"></param>
151         public void RegisterControl(Control control) {
152             RegisterControl(control, false);
153         }
154
155         /// <summary>
156         /// Register a data control to give it Dynamic Data behavior
157         /// </summary>
158         /// <param name="setSelectionFromUrl">When true, if a primary key is found in the route values
159         ///     (typically on the query string), it will get be set as the selected item. This only applies
160         ///     to list controls.</param>
161         public void RegisterControl(Control control, bool setSelectionFromUrl) {
162             // 
163             if (DesignMode) {
164                 return;
165             }
166
167             IDataBoundControlInterface dataBoundControl = DataControlHelper.GetDataBoundControl(control, true /*failIfNotFound*/);
168
169             // If we can't get an associated IDynamicDataSource, don't do anything
170             IDynamicDataSource dataSource = dataBoundControl.DataSourceObject as IDynamicDataSource;
171             if (dataSource == null) {
172                 return;
173             }
174             // If we can't get a MetaTable from the data source, don't do anything
175             MetaTable table = MetaTableHelper.GetTableWithFullFallback(dataSource, Context.ToWrapper());
176             
177             // Save the datasource so we can process its parameters in OnLoad. The value we set is irrelevant
178             _dataSources[dataSource] = null;
179
180             ((INamingContainer)control).SetMetaTable(table);
181
182             BaseDataBoundControl baseDataBoundControl = control as BaseDataBoundControl;
183             if (baseDataBoundControl != null) {
184                 EnablePersistedSelection(baseDataBoundControl, table);
185             }
186
187             RegisterControlInternal(dataBoundControl, dataSource, table, setSelectionFromUrl, Page.IsPostBack);
188         }
189
190         internal static void EnablePersistedSelection(BaseDataBoundControl baseDataBoundControl, IMetaTable table) {
191             Debug.Assert(baseDataBoundControl != null, "NULL!");
192             // Make the persisted selection [....] up with the selected index if possible
193             if (!table.IsReadOnly) {
194                 DynamicDataExtensions.EnablePersistedSelectionInternal(baseDataBoundControl);
195             }
196         }
197
198         internal void RegisterControlInternal(IDataBoundControlInterface dataBoundControl, IDynamicDataSource dataSource, IMetaTable table, bool setSelectionFromUrl, bool isPostBack) {
199             // Set the auto field generator (for controls that support it - GridView and DetailsView)
200             IFieldControl fieldControl = dataBoundControl as IFieldControl;
201             if (fieldControl != null) {
202                 fieldControl.FieldsGenerator = new DefaultAutoFieldGenerator(table);
203             }
204             var linqDataSource = dataSource as LinqDataSource;
205             var entityDataSource = dataSource as EntityDataSource;
206             // If the context type is not set, we need to set it
207             if (dataSource.ContextType == null) {
208                 dataSource.ContextType = table.DataContextType;
209
210                 // If it's a LinqDataSurce, register for ContextCreating so the context gets created using the correct ctor
211                 // Ideally, this would work with other datasource, but we just don't have the right abstraction
212                 if (linqDataSource != null) {
213                     linqDataSource.ContextCreating += delegate(object sender, LinqDataSourceContextEventArgs e) {
214                         e.ObjectInstance = table.CreateContext();
215                     };
216                 }
217
218                 if (entityDataSource != null) {
219                     entityDataSource.ContextCreating += delegate(object sender, EntityDataSourceContextCreatingEventArgs e) {
220                         e.Context = (ObjectContext)table.CreateContext();
221                     };
222                 }
223             }
224
225             // If the datasource doesn't have an EntitySetName (aka TableName), set it from the meta table
226             if (String.IsNullOrEmpty(dataSource.EntitySetName)) {
227                 dataSource.EntitySetName = table.DataContextPropertyName;
228             }
229
230             // If there is no Where clause, turn on auto generate
231             if (String.IsNullOrEmpty(dataSource.Where)) {
232                 dataSource.AutoGenerateWhereClause = true;
233             }
234
235             // If it's a LinqDataSource and the flag is set, pre load the foreign keys
236             if (AutoLoadForeignKeys && linqDataSource != null) {
237                 linqDataSource.LoadWithForeignKeys(table.EntityType);
238             }
239
240             if (!isPostBack) {
241                 if (table.HasPrimaryKey) {
242                     dataBoundControl.DataKeyNames = table.PrimaryKeyNames;
243
244                     // Set the virtual selection from the URL if needed
245                     var dataKeySelector = dataBoundControl as IPersistedSelector;
246                     if (dataKeySelector != null && setSelectionFromUrl) {
247                         DataKey dataKey = table.GetDataKeyFromRoute();
248                         if (dataKey != null) {
249                             dataKeySelector.DataKey = dataKey;
250                         }
251                     }
252                 }
253             }
254         }
255
256
257         internal static IControlParameterTarget GetControlParameterTarget(Control control) {
258             return (control as IControlParameterTarget) ?? new DataBoundControlParameterTarget(control);
259         }
260     }
261 }