Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Web.Entity.Design / System / Data / WebControls / Design / EntityDataSourceConfigureObjectContext.cs
blob24c9e3f49b037356d9a768e9c4122a5285006d8d
1 //------------------------------------------------------------------------------
2 // <copyright file="EntityDataSourceConfigureObjectContext.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //
6 // @owner Microsoft
7 // @backupOwner Microsoft
8 //
9 // Manages the properties that can be set on the first page of the wizard
10 //------------------------------------------------------------------------------
12 using System.Collections.Generic;
13 using System.Web.UI.Design.WebControls.Util;
14 using System.Diagnostics;
15 using System.Globalization;
16 using System.Windows.Forms;
18 namespace System.Web.UI.Design.WebControls
20 // delegate for event handler to process notifications when the DefaultContainerName is changed
21 internal delegate void EntityDataSourceContainerChangedEventHandler(object sender, EntityDataSourceContainerNameItem newContainerName);
23 internal class EntityDataSourceConfigureObjectContext
25 #region Private readonly fields
26 private readonly EntityDataSourceConfigureObjectContextPanel _panel;
27 private readonly EntityDataSourceDesignerHelper _helper;
28 #endregion
30 #region Private writeable fields
31 private EntityDataSourceContainerChangedEventHandler _containerNameChanged; // used to notify the DataSelection panel that a change has been made
32 #endregion
34 #region Private fields for temporary storage of property values
35 private EntityConnectionStringBuilderItem _selectedConnectionStringBuilder;
36 private bool _connectionStringHasValue;
37 private List<EntityConnectionStringBuilderItem> _namedConnections;
38 private List<EntityDataSourceContainerNameItem> _containerNames;
39 private EntityDataSourceContainerNameItem _selectedContainerName;
40 private readonly EntityDataSourceState _entityDataSourceState;
41 private readonly EntityDataSourceWizardForm _wizardForm;
42 #endregion
44 #region Constructors
45 internal EntityDataSourceConfigureObjectContext(EntityDataSourceConfigureObjectContextPanel panel, EntityDataSourceWizardForm wizardForm, EntityDataSourceDesignerHelper helper, EntityDataSourceState entityDataSourceState)
47 try
49 Cursor.Current = Cursors.WaitCursor;
50 _panel = panel;
51 _helper = helper;
53 // Explicitly load metadata here to ensure that we get the latest changes in the project
54 _helper.ReloadResources();
56 _panel.Register(this);
58 _wizardForm = wizardForm;
59 _entityDataSourceState = entityDataSourceState;
61 finally
63 Cursor.Current = Cursors.Default;
66 #endregion
68 #region Events
69 internal event EntityDataSourceContainerChangedEventHandler ContainerNameChanged
71 add
73 _containerNameChanged += value;
75 remove
77 _containerNameChanged -= value;
81 // Fires the event to notify that a container has been chosen from the list
82 private void OnContainerNameChanged(EntityDataSourceContainerNameItem selectedContainerName)
84 if (_containerNameChanged != null)
86 _containerNameChanged(this, selectedContainerName);
90 #endregion
92 #region Methods to manage temporary state and wizard contents
93 // Save current wizard settings back to the EntityDataSourceState
94 internal void SaveState()
96 SaveConnectionString();
97 SaveContainerName();
100 // Load the initial state of the wizard
101 internal void LoadState()
103 LoadConnectionStrings();
104 LoadContainerNames(_entityDataSourceState.DefaultContainerName, true /*initialLoad*/);
107 #region DefaultContainerName
108 /// <summary>
109 /// Populates the DefaultContainerName ComboBox with all of the EntityContainers in the loaded metadata
110 /// If the specified DefaultContainerName property on the data source control is not empty and 'initialLoad' is true,
111 /// it is added to the list and selected in the control
112 /// </summary>
113 /// <param name="containerName">The container name to find</param>
114 /// <param name="initialLoad">if true, this is the initial load so the container name is added to the list if it is not found.</param>
115 private void LoadContainerNames(string containerName, bool initialLoad)
117 // Get a list of EntityContainers from the metadata in the connection string
118 _containerNames = _helper.GetContainerNames(false /*sortResults*/);
120 // Try to find the specified container in list
121 _selectedContainerName = FindContainerName(containerName, initialLoad /*addIfNotFound*/);
123 // Sort the list now, after we may have added a new entry above
124 _containerNames.Sort();
126 // Update the controls
127 _panel.SetContainerNames(_containerNames);
128 _panel.SetSelectedContainerName(_selectedContainerName, initialLoad /*initialLoad*/);
131 /// <summary>
132 /// Find the current container in the current list of containers
133 /// </summary>
134 /// <param name="containerName">The container name to find</param>
135 /// <param name="addIfNotFound">if true, adds the container name to the list if it is not found.</param>
136 /// <returns></returns>
137 private EntityDataSourceContainerNameItem FindContainerName(string containerName, bool addIfNotFound)
139 Debug.Assert(_containerNames != null, "_containerNames have already been initialized and should not be null");
141 if (!String.IsNullOrEmpty(containerName))
143 EntityDataSourceContainerNameItem containerToSelect = null;
144 foreach (EntityDataSourceContainerNameItem containerNameItem in _containerNames)
146 // Ignore case here when searching the list for a matching item, but set the temporary state property to the
147 // correctly-cased version from metadata so that if the user clicks Finish, the correct one will be saved. This
148 // allows some flexibility the designer without preserving an incorrectly-cased value that could cause errors at runtime.
149 if (String.Equals(containerName, containerNameItem.EntityContainerName, StringComparison.OrdinalIgnoreCase))
151 containerToSelect = containerNameItem;
155 // didn't find a matching container, so just create a placeholder for one using the specified name and add it to the list
156 if (containerToSelect == null && addIfNotFound)
158 containerToSelect = new EntityDataSourceContainerNameItem(containerName);
159 _containerNames.Add(containerToSelect);
162 Debug.Assert(addIfNotFound == false || containerToSelect != null, "expected a non-null EntityDataSourceContainerNameItem");
163 return containerToSelect;
166 return null;
169 // Set the container name in temporary storage, update the connection string, and fire the event so the EntitySet will know there has been a change
170 internal void SelectContainerName(EntityDataSourceContainerNameItem selectedContainer)
172 _selectedContainerName = selectedContainer;
174 UpdateWizardState();
175 OnContainerNameChanged(_selectedContainerName);
178 private void SaveContainerName()
180 Debug.Assert(_selectedContainerName != null, "wizard data should not be saved if container name is empty");
181 _entityDataSourceState.DefaultContainerName = _selectedContainerName.EntityContainerName;
183 #endregion
185 #region ConnectionString
186 // Populates the NamedConnection ComboBox with all of the EntityClient connections from the web.config.
187 // If the specified connectionString is a named connection (if it contains "name=ConnectionName"), it is added to the list and selected.
188 // If the specified connectionString is not a named connection, the plain connection string option is selected and populated with the specified value.
189 private void LoadConnectionStrings()
191 // Get a list of all named EntityClient connections in the web.config
192 _namedConnections = _helper.GetNamedEntityClientConnections(false /*sortResults*/);
194 EntityConnectionStringBuilderItem connStrBuilderItem = _helper.GetEntityConnectionStringBuilderItem(_entityDataSourceState.ConnectionString);
195 Debug.Assert(connStrBuilderItem != null, "expected GetEntityConnectionStringBuilder to always return non-null");
197 if (connStrBuilderItem.IsNamedConnection)
199 // Try to find the specified connection in the list or add it
200 connStrBuilderItem = FindCurrentNamedConnection(connStrBuilderItem);
201 Debug.Assert(connStrBuilderItem != null, "expected a non-null connStrBuilderItem for the named connection because it should have added it if it didn't exist");
204 // Sort results now, after we may have added a new item above
205 _namedConnections.Sort();
207 SelectConnectionStringBuilder(connStrBuilderItem, false /*resetContainer*/);
209 // Update the controls
210 _panel.SetNamedConnections(_namedConnections);
211 _panel.SetConnectionString(_selectedConnectionStringBuilder);
214 // Find the current named connection in the list of connections
215 // The returned item may refer to the same connection as the specified item, but it will be the actual reference from the list
216 private EntityConnectionStringBuilderItem FindCurrentNamedConnection(EntityConnectionStringBuilderItem newBuilderItem)
218 Debug.Assert(_namedConnections != null, "_namedConnections should have already been initialized and should not be null");
219 Debug.Assert(newBuilderItem != null && newBuilderItem.IsNamedConnection, "expected non-null newBuilderItem");
221 foreach (EntityConnectionStringBuilderItem namedConnectionItem in _namedConnections)
223 if (((IComparable<EntityConnectionStringBuilderItem>)newBuilderItem).CompareTo(namedConnectionItem) == 0)
225 // returning the one that was actually in the list, so we can select it in the control
226 return namedConnectionItem;
230 // didn't find it in the list, so add it
231 _namedConnections.Add(newBuilderItem);
232 return newBuilderItem;
235 internal EntityConnectionStringBuilderItem GetEntityConnectionStringBuilderItem(string connectionString)
237 return _helper.GetEntityConnectionStringBuilderItem(connectionString);
240 // Set the connection string in temporary storage
241 // Returns true if the metadata was successfully loaded for the specified connections
242 internal bool SelectConnectionStringBuilder(EntityConnectionStringBuilderItem selectedConnection, bool resetContainer)
244 _selectedConnectionStringBuilder = selectedConnection;
246 bool metadataLoaded = false;
247 if (selectedConnection != null)
249 if (selectedConnection.EntityConnectionStringBuilder != null)
251 metadataLoaded = _helper.LoadMetadata(selectedConnection.EntityConnectionStringBuilder);
253 else
255 // Since we don't have a valid connection string builder, we don't have enough information to load metadata.
256 // Clear any existing metadata so we don't see an old item collection on any subsequent calls that access it.
257 // Don't need to display an error here because that was handled by the caller who created the builder item
258 _helper.ClearMetadata();
262 // Reset the list of containers if requested and set the ComboBox to have no selection.
263 // In some cases the containers do not need to be reset because the caller wants to delay that until a later event or wants to preserve a specific value
264 if (resetContainer)
266 string defaultContainerName = _selectedConnectionStringBuilder.EntityConnectionStringBuilder == null ? null : _selectedConnectionStringBuilder.EntityConnectionStringBuilder.Name;
267 LoadContainerNames(defaultContainerName, false /*initialLoad*/);
270 // Update the controls
271 UpdateWizardState();
273 return metadataLoaded;
276 // Set a flag indicating that the connection string textbox or named connection dropdown has a value
277 // This value has not be verified at this point, or may not even be complete, so we don't want to validate it yet and turn it into a builder
278 internal void SelectConnectionStringHasValue(bool connectionStringHasValue)
280 _connectionStringHasValue = connectionStringHasValue;
282 // Update the controls
283 UpdateWizardState();
286 private void SaveConnectionString()
288 Debug.Assert(_selectedConnectionStringBuilder != null, "wizard data should not be saved if connection string is empty");
289 _entityDataSourceState.ConnectionString = _selectedConnectionStringBuilder.ConnectionString;
293 #endregion
294 #endregion
296 #region Wizard button state management
297 // Update the state of the wizard buttons
298 internal void UpdateWizardState()
300 _wizardForm.SetCanNext(this.CanEnableNext);
302 // Finish button should never be enabled at this stage
303 _wizardForm.SetCanFinish(false);
306 // Next button can only be enabled when the following are true:
307 // (1) DefaultContainerName has a value
308 // (2) Either a named connection is selected or the connection string textbox has a value
309 internal bool CanEnableNext
313 return _selectedContainerName != null && _connectionStringHasValue;
316 #endregion