[英]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控件,不需要多行选项。
[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? 有没有办法完全删除此属性? 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.