我有以下课程:
public partial class RichTextBoxEx : RichTextBox
{
public RichTextBoxEx()
{
InitializeComponent();
Text = "Some Text";
}
}
但是,当我将它放在表单上并运行程序时,RichTextBox
为空。有什么问题,我该如何解决?
我假设这里有一些基本的东西,但是我无法弄清楚是什么,而且我没有找到任何关于此的信息。
通常会遵循您在控件的构造函数中设置的属性值。但对于Text
财产,案件有点不同。我已经在另一个answer中描述了它。事实上,它是控制设计师在Text
中设置控件的InitializeNewComponent
属性。
作为一个选项,您可以创建并注册一个新的控件设计器,覆盖InitializeNewComponent
并在调用Text
方法之前捕获base.InitializeNewComponent
属性值。然后在调用base方法之后,再次将Text
属性设置为默认值。
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[Designer(typeof(RichTextBoxExDesigner))]
public class RichTextBoxEx : RichTextBox
{
public RichTextBoxEx ()
{
Text = "Some Text";
}
}
public class RichTextBoxExDesigner : ControlDesigner
{
public override void InitializeNewComponent(System.Collections.IDictionary defaultValues)
{
var txt = Control.Text;
base.InitializeNewComponent(defaultValues);
Control.Text = txt;
}
}
注意:不要忘记添加对System.Design
程序集的引用。
旁注:不适用于Text
属性,但是对于其他类似的情况,当您在构造函数中设置时,您看到属性值不受尊重,另一个嫌疑人是控件的CreateComponentsCore
的ToolboxItem
。对于example AutoSize
的Label
属性。
Text
财产被重置在表格的InitializeComponent
上。
当您查看Designer.cs
的Form
文件时,您应该找到如下所示的行:
private void InitializeComponent()
{
this.richTextBoxEx1 = new WindowsFormsApp1.RichTextBoxEx(); //<-- RichTextBoxEx gets initialized and ITS constructor and InitializeComponent gets called
this.SuspendLayout();
//
// richTextBoxEx1
//
this.richTextBoxEx1.Location = new System.Drawing.Point(322, 106);
this.richTextBoxEx1.Name = "richTextBoxEx1";
this.richTextBoxEx1.Size = new System.Drawing.Size(100, 96);
this.richTextBoxEx1.TabIndex = 0;
this.richTextBoxEx1.Text = ""; //<-- Text Property gets reseted
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.richTextBoxEx1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
你可以通过覆盖OnCreateControl
来克服这一点
所以改变你的控制:
public class RichTextBoxEx : RichTextBox
{
protected override void OnCreateControl()
{
Text = "Hello World";
base.OnCreateControl();
}
}
如果OnCreateControl
被多次调用 - 尽管MSDN上的定义如下:
首次创建控件时,将调用OnCreateControl方法
然后你可以通过使用布尔来强制它被调用一次来跟踪它是否被调用,所以请尝试以下方法:
public class RichTextBoxEx : RichTextBox
{
private bool _initialized = false;
protected override void OnCreateControl()
{
if (!_initialized)
{
_initialized = true;
Text = "Hello World";
}
base.OnCreateControl();
}
}
我不确定你是如何实施你的课程的。当我尝试重现您的问题时,我创建了一个类,然后添加了使用System.Windows.Forms然后创建了该类。就像你做的那样,但我没有最终得到一个公共的分部类,也没有在我的构造函数中调用的InitializeComponent()方法(我必须写)。
码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FormTester
{
public class RichTextboxEx : RichTextBox
{
public RichTextboxEx() : base()
{
Text = "Some Text";
}
}
}
我相信这有效。试试看。
我不清楚你是如何实例化RichTextBox的,所以这可能有用也可能没用......
当你写下你将RichTextBox控件“放在一个表单上”时,我认为这意味着你将控件从工具箱拖放到设计器表面上。如果您已经这样做了,那么您将获得RichTextBox的实例而不是RichTextBoxEx。
要获取RichTextBoxEx的实例,可以将其编译为DLL并将其添加到工具箱中。
另一种方法是让您更好地控制对象实例化/初始化,它是在代码中实例化它并以这种方式将其添加到您的表单中。在窗体的构造函数中,您可以这样做:
var richTextBoxEx = new RichTextBoxEx();
// set your richTextBoxEx properties here
richTextBoxEx.Top = 100;
richTextBoxEx.Left = 100;
this.Controls.Add(richTextBoxEx);
虽然您可以如上所示设置属性,但您也可以在子类控件的构造函数中执行此操作(就像您一样)。
我希望这提供了另一种方法来解决这个问题。