1 namespace System.Web.DynamicData {
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;
10 using System.Globalization;
11 using System.Security.Permissions;
12 using System.Web.Resources;
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;
20 /// Adds behavior to certain control to make them work with Dynamic Data
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>();
33 /// Causes foreign entities to be loaded as well setting the proper DataLoadOptions.
34 /// Only works with Linq To Sql.
39 ResourceDescription("DynamicDataManager_AutoLoadForeignKeys")
41 public bool AutoLoadForeignKeys {
48 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
49 EditorBrowsable(EditorBrowsableState.Never)
51 public override string ClientID {
59 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
60 EditorBrowsable(EditorBrowsableState.Never)
62 public override ClientIDMode ClientIDMode {
64 return base.ClientIDMode;
67 throw new NotImplementedException();
74 PersistenceMode(PersistenceMode.InnerProperty),
75 MergableProperty(false),
77 public DataControlReferenceCollection DataControls {
79 if (_dataControls == null) {
80 _dataControls = new DataControlReferenceCollection(this);
87 /// See base class documentation
91 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
92 EditorBrowsable(EditorBrowsableState.Never)
94 public override bool Visible {
99 throw new NotImplementedException();
104 /// See base class documentation
106 [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
107 protected override void OnInit(EventArgs e) {
110 // Initialize the collection
111 DataControls.Initialize();
113 // Subscribe to the Page's Init to register the controls set in the DataControls collection
114 Page.Init += OnPageInit;
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));
128 RegisterControl(targetControl);
133 /// See base class documentation
135 [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
136 protected override void OnLoad(EventArgs e) {
139 // Go through all the registered data sources
140 foreach (IDynamicDataSource dataSource in _dataSources.Keys) {
142 // Expand any dynamic where parameters that they may use
143 dataSource.ExpandDynamicWhereParameters();
148 /// Register a data control to give it Dynamic Data behavior
150 /// <param name="control"></param>
151 public void RegisterControl(Control control) {
152 RegisterControl(control, false);
156 /// Register a data control to give it Dynamic Data behavior
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) {
167 IDataBoundControlInterface dataBoundControl = DataControlHelper.GetDataBoundControl(control, true /*failIfNotFound*/);
169 // If we can't get an associated IDynamicDataSource, don't do anything
170 IDynamicDataSource dataSource = dataBoundControl.DataSourceObject as IDynamicDataSource;
171 if (dataSource == null) {
174 // If we can't get a MetaTable from the data source, don't do anything
175 MetaTable table = MetaTableHelper.GetTableWithFullFallback(dataSource, Context.ToWrapper());
177 // Save the datasource so we can process its parameters in OnLoad. The value we set is irrelevant
178 _dataSources[dataSource] = null;
180 ((INamingContainer)control).SetMetaTable(table);
182 BaseDataBoundControl baseDataBoundControl = control as BaseDataBoundControl;
183 if (baseDataBoundControl != null) {
184 EnablePersistedSelection(baseDataBoundControl, table);
187 RegisterControlInternal(dataBoundControl, dataSource, table, setSelectionFromUrl, Page.IsPostBack);
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);
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);
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;
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();
218 if (entityDataSource != null) {
219 entityDataSource.ContextCreating += delegate(object sender, EntityDataSourceContextCreatingEventArgs e) {
220 e.Context = (ObjectContext)table.CreateContext();
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;
230 // If there is no Where clause, turn on auto generate
231 if (String.IsNullOrEmpty(dataSource.Where)) {
232 dataSource.AutoGenerateWhereClause = true;
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);
241 if (table.HasPrimaryKey) {
242 dataBoundControl.DataKeyNames = table.PrimaryKeyNames;
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;
257 internal static IControlParameterTarget GetControlParameterTarget(Control control) {
258 return (control as IControlParameterTarget) ?? new DataBoundControlParameterTarget(control);