| File: System\Windows\Forms\Design\EditorServiceContext.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing.Design; namespace System.Windows.Forms.Design; /// <summary> /// Provides an implementation of IWindowsFormsEditorService and ITypeDescriptorContext. /// Also provides a static method to invoke a UITypeEditor given a designer, an object and a property name. /// </summary> internal class EditorServiceContext : IWindowsFormsEditorService, ITypeDescriptorContext { private readonly ComponentDesigner _designer; private IComponentChangeService? _componentChangeService; private readonly PropertyDescriptor? _targetProperty; internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor? prop) { _designer = designer; _targetProperty = prop; if (prop is null) { prop = TypeDescriptor.GetDefaultProperty(designer.Component); if (prop is not null && typeof(ICollection).IsAssignableFrom(prop.PropertyType)) { _targetProperty = prop; } } Debug.Assert(_targetProperty is not null, "Need PropertyDescriptor for ICollection property to associate collection editor with."); } internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor? prop, string newVerbText) : this(designer, prop) { Debug.Assert(!string.IsNullOrEmpty(newVerbText), "newVerbText cannot be null or empty"); _designer.Verbs?.Add(new DesignerVerb(newVerbText, new EventHandler(OnEditItems))); } public static object? EditValue(ComponentDesigner designer, object objectToChange, string propName) { // Get PropertyDescriptor PropertyDescriptor descriptor = TypeDescriptor.GetProperties(objectToChange)[propName]!; // Create a Context EditorServiceContext context = new(designer, descriptor); // Get Editor UITypeEditor editor = descriptor.GetEditor<UITypeEditor>()!; // Get value to edit object? value = descriptor.GetValue(objectToChange); // Edit value object? newValue = editor.EditValue(context, context, value); if (newValue != value) { try { descriptor.SetValue(objectToChange, newValue); } catch (CheckoutException) { } } return newValue; } /// <summary> /// Our caching property for the IComponentChangeService /// </summary> private IComponentChangeService ChangeService => _componentChangeService ??= this.GetRequiredService<IComponentChangeService>(); /// <inheritdoc /> IContainer? ITypeDescriptorContext.Container => _designer.Component.Site?.Container; /// <inheritdoc /> void ITypeDescriptorContext.OnComponentChanged() => ChangeService.OnComponentChanged(_designer.Component, _targetProperty); /// <inheritdoc /> bool ITypeDescriptorContext.OnComponentChanging() { try { ChangeService.OnComponentChanging(_designer.Component, _targetProperty); return true; } catch (CheckoutException checkoutException) when (checkoutException == CheckoutException.Canceled) { return false; } } object ITypeDescriptorContext.Instance => _designer.Component; PropertyDescriptor? ITypeDescriptorContext.PropertyDescriptor => _targetProperty; object? IServiceProvider.GetService(Type serviceType) { if (serviceType == typeof(ITypeDescriptorContext) || serviceType == typeof(IWindowsFormsEditorService)) { return this; } return _designer.Component?.Site?.GetService(serviceType); } void IWindowsFormsEditorService.CloseDropDown() { // we'll never be called to do this. Debug.Fail("NOTIMPL"); return; } void IWindowsFormsEditorService.DropDownControl(Control control) { Debug.Fail("NOTIMPL"); return; } DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog) { IUIService? uiSvc = this.GetService<IUIService>(); if (uiSvc is not null) { return uiSvc.ShowDialog(dialog); } else { return dialog.ShowDialog(_designer.Component as IWin32Window); } } /// <summary> /// When the verb is invoked, use all the stuff above to show the dialog, etc. /// </summary> private void OnEditItems(object? sender, EventArgs e) { object? propertyValue = _targetProperty?.GetValue(_designer.Component); if (propertyValue is null) { return; } CollectionEditor? itemsEditor = TypeDescriptor.GetEditor(propertyValue, typeof(UITypeEditor)) as CollectionEditor; Debug.Assert(itemsEditor is not null, $"Didn't get a collection editor for type '{_targetProperty!.PropertyType.FullName}'"); itemsEditor?.EditValue(this, this, propertyValue); } }