| File: System\Windows\Forms\Design\DataGridViewColumnDesigner.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.ComponentModel.Design.Serialization; using System.Windows.Forms.Design.Behavior; namespace System.Windows.Forms.Design; internal class DataGridViewColumnDesigner : ComponentDesigner { private const int DATAGRIDVIEWCOLUMN_defaultWidth = 100; private bool _userAddedColumn; private bool _initializing; private BehaviorService? _behaviorService; private ISelectionService? _selectionService; private FilterCutCopyPasteDeleteBehavior? _behavior; private bool _behaviorPushed; private DataGridView? _liveDataGridView; private string? Name { get { DataGridViewColumn col = (DataGridViewColumn)Component; return col.Site is not null ? col.Site.Name : col.Name; } set { value ??= string.Empty; DataGridViewColumn? col = (DataGridViewColumn)Component; if (col is null) { return; } // Note: case sensitive because lookup inside DataGridViewColumnCollection is case sensitive. if (string.Compare(value, col.Name, false, Globalization.CultureInfo.InvariantCulture) == 0) { return; } DataGridView? dataGridView = col.DataGridView; IDesignerHost? host = null; INameCreationService? nameCreationService = null; if (dataGridView is not null && dataGridView.Site is not null) { host = dataGridView.Site.GetService<IDesignerHost>(); nameCreationService = dataGridView.Site.GetService<INameCreationService>(); } IContainer? container = host?.Container; // ValidName() checks any name conflicts on the DGV's column collection as well as any name conflicts // on the Container::Components collection. if (dataGridView is not null && !DataGridViewAddColumnDialog.ValidName(value, dataGridView.Columns, container, nameCreationService, _liveDataGridView?.Columns, true, out string errorString)) { if (dataGridView is not null && dataGridView.Site is not null) { IUIService? uiService = dataGridView.Site.GetService<IUIService>(); DataGridViewDesigner.ShowErrorDialog(uiService, errorString, _liveDataGridView); } return; } // we are good. // Set the site name if the column is sited. // Then set the column name. if ((host is null || (host is not null && !host.Loading)) && Component.Site is not null) { Component.Site.Name = value; } col.Name = value; } } public DataGridView LiveDataGridView { set { _liveDataGridView = value; } } /// <devdoc> /// vsw 311922. /// We want to add a design time only property which tracks if the user added this column or not. /// Because this is a design time only property, it will be saved to *resx file. /// Hence, its value will be saved from session to session. /// /// The property is set in ONLY one place and is used in ONLY one place. /// /// This property is set ONLY the user adds a column via the data grid view add column dialog. /// If columns are added as a result of binding the data grid view to a data source or as a result /// of meta data changes then they are not considered to be added by user. /// /// This property is used ONLY by the data grid view designer when it has to decide whether or not to remove /// a data bound property. /// </devdoc> private bool UserAddedColumn { get => _userAddedColumn; set => _userAddedColumn = value; } private int Width { get { DataGridViewColumn col = (DataGridViewColumn)Component; return col.Width; } set { DataGridViewColumn col = (DataGridViewColumn)Component; value = Math.Max(col.MinimumWidth, value); col.Width = value; } } public override void Initialize(IComponent component) { _initializing = true; base.Initialize(component); if (component.Site is not null) { // Acquire a reference to ISelectionService. _selectionService = GetService<ISelectionService>(); Debug.Assert(_selectionService is not null); // Acquire a reference to BehaviorService. _behaviorService = GetService<BehaviorService>(); if (_behaviorService is not null && _selectionService is not null) { _behavior = new FilterCutCopyPasteDeleteBehavior(true, _behaviorService); UpdateBehavior(); _selectionService.SelectionChanged += selectionService_SelectionChanged; } } _initializing = false; } protected override void Dispose(bool disposing) { if (disposing) { PopBehavior(); _selectionService?.SelectionChanged -= selectionService_SelectionChanged; _selectionService = null; _behaviorService = null; } } private void PushBehavior() { if (!_behaviorPushed) { Debug.Assert(_behavior is not null); try { _behaviorService?.PushBehavior(_behavior); } finally { _behaviorPushed = true; } } } private void PopBehavior() { if (_behaviorPushed) { Debug.Assert(_behavior is not null); try { _behaviorService?.PopBehavior(_behavior); } finally { _behaviorPushed = false; } } } private void UpdateBehavior() { if (_selectionService is not null) { if (_selectionService.PrimarySelection is not null && Component.Equals(_selectionService.PrimarySelection)) { PushBehavior(); } else { // ensure we are popped off PopBehavior(); } } } private void selectionService_SelectionChanged(object? sender, EventArgs e) { UpdateBehavior(); } protected override void PreFilterProperties(IDictionary properties) { base.PreFilterProperties(properties); PropertyDescriptor? prop = properties["Width"] as PropertyDescriptor; if (prop is not null) { properties["Width"] = TypeDescriptor.CreateProperty(typeof(DataGridViewColumnDesigner), prop, []); } prop = properties["Name"] as PropertyDescriptor; if (prop is not null) { if (Component.Site is null) { // When the Site is not null the Extender provider will add the (Name) property. // However, when columns are on the data grid view column collection editor, the site is null. // In that case we have to make the (Name) property browsable true. properties["Name"] = TypeDescriptor.CreateProperty(typeof(DataGridViewColumnDesigner), prop, BrowsableAttribute.Yes, CategoryAttribute.Design, new DescriptionAttribute(SR.DesignerPropName), new ParenthesizePropertyNameAttribute(true)); } else { // When the column is sited use DataGridViewColumnDesigner::Name property // so it can use the Name validation logic specific to DataGridViewColumnCollection. properties["Name"] = TypeDescriptor.CreateProperty(typeof(DataGridViewColumnDesigner), prop, new ParenthesizePropertyNameAttribute(true)); } } // Add the UserAddedColumn design time only property. properties["UserAddedColumn"] = TypeDescriptor.CreateProperty(typeof(DataGridViewColumnDesigner), "UserAddedColumn", typeof(bool), new DefaultValueAttribute(false), BrowsableAttribute.No, DesignOnlyAttribute.Yes); } private bool ShouldSerializeWidth() { DataGridViewColumn col = (DataGridViewColumn)Component; return col.InheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.Fill && col.Width != DATAGRIDVIEWCOLUMN_defaultWidth; } private bool ShouldSerializeName() { if (!TryGetService(out IDesignerHost? host)) { // The column is hosted in the column collection dialog. // Return false : let the user type whatever he feels like. return false; } return _initializing ? (Component != host.RootComponent) // for non root components, respect the name that the base Control serialized unless changed : ShadowProperties.ShouldSerializeValue(nameof(Name), null); } public class FilterCutCopyPasteDeleteBehavior : Behavior.Behavior { public FilterCutCopyPasteDeleteBehavior(bool callParentBehavior, BehaviorService behaviorService) : base(callParentBehavior, behaviorService) { } public override MenuCommand? FindCommand(CommandID commandId) { MenuCommand command; if ((commandId.ID == StandardCommands.Copy.ID) && (commandId.Guid == StandardCommands.Copy.Guid)) { command = new MenuCommand(handler, StandardCommands.Copy) { Enabled = false }; return command; } if ((commandId.ID == StandardCommands.Paste.ID) && (commandId.Guid == StandardCommands.Paste.Guid)) { command = new MenuCommand(handler, StandardCommands.Paste) { Enabled = false }; return command; } if ((commandId.ID == StandardCommands.Delete.ID) && (commandId.Guid == StandardCommands.Delete.Guid)) { command = new MenuCommand(handler, StandardCommands.Delete) { Enabled = false }; return command; } if ((commandId.ID == StandardCommands.Cut.ID) && (commandId.Guid == StandardCommands.Cut.Guid)) { command = new MenuCommand(handler, StandardCommands.Cut) { Enabled = false }; return command; } return base.FindCommand(commandId); } private void handler(object? sender, EventArgs e) { } } }