简体   繁体   English

如何删除自定义TextBox控件中的Multiline属性?

[英]How to remove the Multiline property in custom TextBox control?

I'm creating a custom TextBox control in winforms and I don't need the multiline option. 我在winforms中创建一个自定义TextBox控件,不需要多行选项。

  1. In this case, I think that the arrow button in the designer that shows a dropdown with a Multiline option checkbox is useless. 在这种情况下,我认为设计器中显示带有多行选项复选框的下拉菜单的箭头按钮是无用的。 Is it possible somehow to get rid of it? 是否有可能摆脱它?

这是按钮

  1. I achieved to hide the Multiline property from the properties group by overriding it in the custom Textbox class and setting [Browsable(flase)] . 通过在自定义Textbox类中重写Multiline属性并设置[Browsable(flase)]我实现了从属性组隐藏Multiline属性。 However, it's still possible to change it from code. 但是,仍然可以从代码中进行更改。 Is there a way to completely remove this attribute? 有没有办法完全删除此属性?
    Found something here ( How to remove a property from a custom user control ), but I don't how this could help me. 在这里找到了一些东西( 如何从自定义用户控件中删除属性 ),但是我对此没有帮助。

When you inherit from a class, you shouldn't remove features of the parent. 从类继承时,不应删除父级的功能。 Anyone should be able to use your class in place of the parent class (this is known as the Liskov Substitution Principle). 任何人都应该能够使用您的班级代替父班级(这被称为Liskov替代原理)。

It sounds like you want to make a control that hosts a TextBox control instead. 听起来您想制作一个承载 TextBox控件。 This allows you to have full control over which properties you expose, and doesn't violate the contract of the TextBox class. 这使您可以完全控制公开的属性,并且不会违反TextBox类的协定。

The arrow button in the designer that shows a dropdown with a Multiline option checkbox is called a SmartTag. 设计器中显示带有“多行选项”复选框的下拉菜单箭头按钮称为SmartTag。

To speed development, many controls offer smart tags, which are context-sensitive menus that allow you to perform common tasks like these in a single gesture at design time. 为了加快开发速度,许多控件都提供了智能标记,这些标记是上下文相关的菜单,可让您在设计时以单个手势执行诸如此类的常见任务。 These tasks are called smart-tag verbs. 这些任务称为智能标记动词。

The TextBox SmartTag is generated based on properties exposed by its designer (System.Windows.Forms.Design.TextBoxDesigner); TextBox SmartTag是根据其设计器(System.Windows.Forms.Design.TextBoxDesigner)公开的属性生成的; specifically the the ActionLists Property that it inherits from its ancestor ComponentDesigner . 特别是它从其祖先ComponentDesigner继承的ActionLists属性 ActionLists is a collection of DesignerActionList objects. ActionLists是DesignerActionList对象的集合。

You could create a custom control designer that does not define a SmartTag and assign it as the designer for your custom control. 您可以创建一个未定义SmartTag的自定义控件设计器,然后将其分配为自定义控件的设计器。 However this would require you to re-implement all the features of the TextBoxDesigner to provide an expected design experience as TextBoxDesigner is an internal class and can not be inherited. 但是,这将要求您重新实现TextBoxDesigner的所有功能,以提供预期的设计体验,因为TextBoxDesigner是一个内部类,无法继承。 A simpler method is to hook into the available designer services and obtain a reference to the default TextBoxDesigner. 一种更简单的方法是挂接到可用的设计器服务并获得对默认TextBoxDesigner的引用。 This is done by overriding the control's Site Property . 这是通过覆盖控件的Site Property来完成的

// add project assembly reference: System.Design
using System.Windows.Forms;
using System.ComponentModel;
using System.ComponentModel.Design;
using System;
using System.Windows.Forms.Design;

public class SingleLineTB : TextBox
{
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
    public override bool Multiline
    {
        get {return base.Multiline;}
        set {}
    }

    #region Designer Services
    private IDesignerHost designerHost;

    public override ISite Site
    {
        get {return base.Site;}
        set 
        {
            base.Site = value;
            if (value == null)
            {
                // this instance is being removed from the design surface
                DetachDesignerServices();
            }
            else // being added to the design surface
            {
                designerHost = (IDesignerHost)value.GetService(typeof(IDesignerHost));
                if (designerHost != null)
                {
                    if (designerHost.Loading)
                    {
                        // the designer has not finished loading, 
                        // postpone all other connections until it has finished loading
                        designerHost.LoadComplete += DesignerHostLoaded;
                    }
                    else
                    {
                        if (designerHost.InTransaction)
                        {
                            // designerHost loaded, but is in the in the process of creating this instance
                            designerHost.TransactionClosed += DesignerTransactionClosed;
                        }
                        else
                        {
                            // this will probably never be hit as the designer
                            // should be siting the component in a transaction
                            ClearDesignerActionLists();
                        }
                    }
                }
            }
        }
    }

    private void DesignerHostLoaded(object sender, EventArgs e)
    {
        designerHost.LoadComplete -= DesignerHostLoaded;
        ClearDesignerActionLists();
    }

    private void DesignerTransactionClosed(object sender, DesignerTransactionCloseEventArgs e)
    {
        designerHost.TransactionClosed -= DesignerTransactionClosed;
        ClearDesignerActionLists();
    }
    private void DetachDesignerServices()
    {
        if (designerHost != null)
        {
            designerHost.TransactionClosed -= DesignerTransactionClosed;
            designerHost.LoadComplete -= DesignerHostLoaded;
            designerHost = null;
        }
    }

    private void ClearDesignerActionLists()
    {
        ControlDesigner myDesigner = designerHost.GetDesigner(this) as ControlDesigner;
        myDesigner?.ActionLists.Clear();
    }

    #endregion // "Designer Services
}

The code first obtains a reference to the designer host and the uses that reference to obtain a reference to the control's designer. 该代码首先获取对设计器主机的引用,并使用该引用获取对控件设计器的引用。 Once the designer reference is obtained, it is possible to clear the ActionLists collection to prevent the generation of the SmartTag. 一旦获得设计者参考,便可以清除ActionLists集合以防止生成SmartTag。

Your second requested feature to totally remove the MultiLine Property is not possible as you can not uninherit a property. 不能完全继承 MultiLine属性是您第二个请求的功能,因为您不能取消继承该属性。 The best you can do is hide it as much as possible for the code editor. 您能做的最好的事情就是尽可能地将其隐藏在代码编辑器中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM