| File: System\Windows\Forms\Design\MaskedTextBoxDesigner.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.Globalization; namespace System.Windows.Forms.Design; /// <summary> /// Designer class for the MaskedTextBox control. /// </summary> internal class MaskedTextBoxDesigner : TextBoxBaseDesigner { private DesignerVerbCollection? _verbs; private DesignerActionListCollection? _actions; // Overridden to avoid setting the default property ("Mask") // to the Site.Name (i.e. maskedTextBox1). protected override bool SetTextualDefaultProperty => false; /// <summary> /// MaskedTextBox designer action list property. Gets the design-time supported actions on the control. /// </summary> public override DesignerActionListCollection ActionLists { get { if (_actions is null) { _actions = new DesignerActionListCollection(); _actions.Add(new MaskedTextBoxDesignerActionList(this)); } return _actions; } } /// <summary> /// A utility method to get a design time masked text box based on the masked text box being designed. /// </summary> /// <param name="maskedTextBox">The masked text box.</param> /// <returns></returns> internal static MaskedTextBox GetDesignMaskedTextBox(MaskedTextBox maskedTextBox) { MaskedTextBox designMaskedTextBox; if (maskedTextBox is null) { // return a default control. designMaskedTextBox = new MaskedTextBox(); } else { MaskedTextProvider? maskedTextProvider = maskedTextBox.MaskedTextProvider; if (maskedTextProvider is null) { designMaskedTextBox = new MaskedTextBox { Text = maskedTextBox.Text }; } else { designMaskedTextBox = new MaskedTextBox(maskedTextProvider); } // Clone MTB properties. designMaskedTextBox.ValidatingType = maskedTextBox.ValidatingType; designMaskedTextBox.BeepOnError = maskedTextBox.BeepOnError; designMaskedTextBox.InsertKeyMode = maskedTextBox.InsertKeyMode; designMaskedTextBox.RejectInputOnFirstFailure = maskedTextBox.RejectInputOnFirstFailure; designMaskedTextBox.CutCopyMaskFormat = maskedTextBox.CutCopyMaskFormat; designMaskedTextBox.Culture = maskedTextBox.Culture; // designMaskedTextBox.TextMaskFormat = maskedTextBox.TextMaskFormat; - Not relevant since it is to be used programmatically only. } // Some constant properties at design time. designMaskedTextBox.UseSystemPasswordChar = false; designMaskedTextBox.PasswordChar = '\0'; designMaskedTextBox.ReadOnly = false; designMaskedTextBox.HidePromptOnLeave = false; return designMaskedTextBox; } internal static string GetMaskInputRejectedErrorMessage(MaskInputRejectedEventArgs e) { string rejectionHint; switch (e.RejectionHint) { case MaskedTextResultHint.AsciiCharacterExpected: rejectionHint = SR.MaskedTextBoxHintAsciiCharacterExpected; break; case MaskedTextResultHint.AlphanumericCharacterExpected: rejectionHint = SR.MaskedTextBoxHintAlphanumericCharacterExpected; break; case MaskedTextResultHint.DigitExpected: rejectionHint = SR.MaskedTextBoxHintDigitExpected; break; case MaskedTextResultHint.LetterExpected: rejectionHint = SR.MaskedTextBoxHintLetterExpected; break; case MaskedTextResultHint.SignedDigitExpected: rejectionHint = SR.MaskedTextBoxHintSignedDigitExpected; break; case MaskedTextResultHint.PromptCharNotAllowed: rejectionHint = SR.MaskedTextBoxHintPromptCharNotAllowed; break; case MaskedTextResultHint.UnavailableEditPosition: rejectionHint = SR.MaskedTextBoxHintUnavailableEditPosition; break; case MaskedTextResultHint.NonEditPosition: rejectionHint = SR.MaskedTextBoxHintNonEditPosition; break; case MaskedTextResultHint.PositionOutOfRange: rejectionHint = SR.MaskedTextBoxHintPositionOutOfRange; break; case MaskedTextResultHint.InvalidInput: rejectionHint = SR.MaskedTextBoxHintInvalidInput; break; case MaskedTextResultHint.Unknown: default: Debug.Fail("Unknown RejectionHint, defaulting to InvalidInput..."); goto case MaskedTextResultHint.InvalidInput; } return string.Format(CultureInfo.CurrentCulture, SR.MaskedTextBoxTextEditorErrorFormatString, e.Position, rejectionHint); } /// <summary> /// Obsolete ComponentDesigner method which sets component default properties. Overridden to avoid setting /// the Mask improperly. /// </summary> [Obsolete("This method has been deprecated. Use InitializeNewComponent instead. https://go.microsoft.com/fwlink/?linkid=14202")] public override void OnSetComponentDefaults() { // do nothing. } /// <summary> /// Event handler for the set mask verb. /// </summary> private void OnVerbSetMask(object? sender, EventArgs e) { MaskedTextBoxDesignerActionList actionList = new(this); actionList.SetMask(); } /// <summary> /// Allows a designer to filter the set of properties /// the component it is designing will expose through the /// TypeDescriptor object. This method is called /// immediately before its corresponding "Post" method. /// If you are overriding this method you should call /// the base implementation before you perform your own /// filtering. /// </summary> protected override void PreFilterProperties(IDictionary properties) { base.PreFilterProperties(properties); string[] shadowProps = [ "Text", "PasswordChar" ]; Attribute[] empty = []; PropertyDescriptor? prop; for (int i = 0; i < shadowProps.Length; i++) { prop = (PropertyDescriptor?)properties[shadowProps[i]]; if (prop is not null) { properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(MaskedTextBoxDesigner), prop, empty); } } } /// <summary> /// Retrieves a set of rules concerning the movement capabilities of a component. /// This should be one or more flags from the SelectionRules class. If no designer /// provides rules for a component, the component will not get any UI services. /// </summary> public override SelectionRules SelectionRules { get { SelectionRules rules = base.SelectionRules; rules &= ~(SelectionRules.TopSizeable | SelectionRules.BottomSizeable); // Height is fixed. return rules; } } /// <summary> /// Shadows the PasswordChar. UseSystemPasswordChar overrides PasswordChar so independent on the value /// of PasswordChar it will return the system password char. However, the value of PasswordChar is /// cached so if UseSystemPasswordChar is reset at design time the PasswordChar value can be restored. /// So in the case both properties are set, we need to serialize the real PasswordChar value as well. /// </summary> private char PasswordChar { get { MaskedTextBox? maskedTextBox = Control as MaskedTextBox; Debug.Assert(maskedTextBox is not null, "Designed control is not a MaskedTextBox."); if (maskedTextBox.UseSystemPasswordChar) { maskedTextBox.UseSystemPasswordChar = false; char pwdChar = maskedTextBox.PasswordChar; maskedTextBox.UseSystemPasswordChar = true; return pwdChar; } else { return maskedTextBox.PasswordChar; } } set { MaskedTextBox? maskedTextBox = Control as MaskedTextBox; Debug.Assert(maskedTextBox is not null, "Designed control is not a MaskedTextBox."); maskedTextBox.PasswordChar = value; } } /// <summary> /// Shadow the Text property to do two things: /// 1. Always show the text without prompt or literals. /// 2. The text from the UITypeEditor is assigned escaping literals, prompt and spaces, this is to allow for partial inputs. /// Observe that if the MTB is hooked to a PropertyBrowser at design time, shadowing of the property won't work unless the /// application is a well written control designer (implements corresponding interfaces). /// </summary> private string? Text { get { // Return text w/o literals or prompt. MaskedTextBox? maskedTextBox = Control as MaskedTextBox; Debug.Assert(maskedTextBox is not null, "Designed control is not a MaskedTextBox."); // Text w/o prompt or literals. if (string.IsNullOrEmpty(maskedTextBox.Mask)) { return maskedTextBox.Text; } return maskedTextBox.MaskedTextProvider?.ToString(includePrompt: false, includeLiterals: false); } set { MaskedTextBox? maskedTextBox = Control as MaskedTextBox; Debug.Assert(maskedTextBox is not null, "Designed control is not a MaskedTextBox."); if (string.IsNullOrEmpty(maskedTextBox.Mask)) { maskedTextBox.Text = value; } else { bool ResetOnSpace = maskedTextBox.ResetOnSpace; bool ResetOnPrompt = maskedTextBox.ResetOnPrompt; bool SkipLiterals = maskedTextBox.SkipLiterals; maskedTextBox.ResetOnSpace = true; maskedTextBox.ResetOnPrompt = true; maskedTextBox.SkipLiterals = true; // Value is expected to contain literals and prompt. maskedTextBox.Text = value; maskedTextBox.ResetOnSpace = ResetOnSpace; maskedTextBox.ResetOnPrompt = ResetOnPrompt; maskedTextBox.SkipLiterals = SkipLiterals; } } } /// <summary> /// MaskedTextBox designer verb collection property. Gets the design-time supported verbs of the control. /// </summary> public override DesignerVerbCollection Verbs { get { if (_verbs is null) { _verbs = new DesignerVerbCollection(); _verbs.Add(new DesignerVerb(SR.MaskedTextBoxDesignerVerbsSetMaskDesc, new EventHandler(OnVerbSetMask))); } return _verbs; } } }