简体   繁体   English

在构造函数中更改扩展的RichTextBox文本不起作用

[英]Changing an extended RichTextBox text in constructor doesn't work

I have the following class: 我有以下课程:

public partial class RichTextBoxEx : RichTextBox
{
    public RichTextBoxEx()
    {
        InitializeComponent();
        Text = "Some Text";
    }
}

However, when I place it over a form and run the program, the RichTextBox is empty. 但是,当我将其放在窗体上并运行程序时, RichTextBox为空。 What is the problem and how can I fix it? 有什么问题,我该如何解决?

在此处输入图片说明

I assume there is something basic I'm missing here, but I cannot figure out what, and I did not manage to find any information about this. 我认为这里缺少一些基本信息,但是我无法弄清楚是什么,因此我也没有找到任何有关此信息。

The property values which you set in constructor of the control are usually respected. 通常会尊重您在控件的构造函数中设置的属性值。 But for Text property, the case is a bit different. 但是对于Text属性,情况有所不同。 I've already described about it in another answer . 我已经在另一个答案中对此进行了描述。 In fact it's the control designer which sets Text property of the control in InitializeNewComponent . 实际上,是控件设计器在InitializeNewComponent设置了控件的Text属性。

As an option, you can create and register a new control designer, override InitializeNewComponent and capture the Text property value before calling base.InitializeNewComponent method. 作为一种选择,您可以创建并注册一个新的控件设计器,重写InitializeNewComponent并捕获Text属性值,然后调用base.InitializeNewComponent方法。 Then after calling base method, set the Text property again to the default value. 然后,在调用基本方法之后,再次将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;
    }
}

Note: Don't forget adding reference to System.Design assembly. 注意:不要忘记添加对System.Design程序集的引用。

Side note: Not for Text property, but for other similar cases which you see a property value is not respected when you set in constructor, another suspect is CreateComponentsCore of ToolboxItem of the control. 旁注:不是Text属性,但是对于其他类似情况,当您在构造函数中进行设置时看到属性值不被尊重,另一个ToolboxItem是控件的ToolboxItemCreateComponentsCore For example for AutoSize property of the Label . 例如Label AutoSize属性。

The Text property gets reseted upon InitializeComponent of the Form. Text属性在窗体的InitializeComponent上重置。

When you have a look at the Designer.cs file of the Form you should find a line like the following: 当您查看FormDesigner.cs文件时,应该找到类似于以下内容的行:

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);

}

You can overcome this by overriding the OnCreateControl 您可以通过重写OnCreateControl来克服此问题

So change your control to this: 因此,将控件更改为此:

public class RichTextBoxEx : RichTextBox
{
    protected override void OnCreateControl()
    {
        Text = "Hello World";
        base.OnCreateControl();
    }
}

If the OnCreateControl gets called multiple times - altough the definition of it on MSDN states: 如果OnCreateControl被多次调用-完全在MSDN上定义如下:

The OnCreateControl method is called when the control is first created 首次创建控件时调用OnCreateControl方法

Then you could force it to be called once by using a boolean to track if it got called or not, so try the following: 然后,可以通过使用布尔值来跟踪它是否被调用来强制一次调用它,因此请尝试以下操作:

public class RichTextBoxEx : RichTextBox
{
    private bool _initialized = false;
    protected override void OnCreateControl()
    {
        if (!_initialized)
        {
            _initialized = true;
            Text = "Hello World";
        }

        base.OnCreateControl();
    }
}

I'm not sure how you implemented your class. 我不确定您是如何实现课程的。 When I tried to reproduce your problem, I made a class and then added the using System.Windows.Forms then created the class. 当我尝试重现您的问题时,我创建了一个类,然后添加了使用System.Windows.Forms的类,然后创建了该类。 Much as you did, but I didn't end up with a public partial class nor an InitializeComponent() method called in my constructor (which I had to write). 就像您所做的一样,但是我没有得到一个公共的局部类,也没有得到构造函数中调用的InitializeComponent()方法(必须编写)。

Code: 码:

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";
        }
    }
}

I believe this worked as you had intended. 我相信这可以按照您的预期工作。 Give it a try. 试试看。

It wasn't clear to me how you were instantiating the RichTextBox, so this might or might not be useful... 我不清楚您是如何实例化RichTextBox的,所以这可能有用也可能没有用...

When you wrote that you placed a RichTextBox control "over a form", I assumed that meant that you drag/dropped the control from the toolbox onto the designer surface. 当您写到将RichTextBox控件“放置在表单上”时,我认为那意味着您将控件从工具箱拖放到设计器图面上。 If you had done that, then you would be getting an instance of RichTextBox and not RichTextBoxEx. 如果这样做了,那么您将获得RichTextBox的实例,而不是RichTextBoxEx的实例。

To get an instance of RichTextBoxEx, you could compile it to a DLL and add it to your toolbox. 要获取RichTextBoxEx的实例,可以将其编译为DLL并将其添加到工具箱中。

An alternative approach, giving you some more control over object instantiation/inititialization, is to instantiate it in code and add it to your form that way. 一种替代方法可以使您对对象实例化/初始化进行更多控制,方法是在代码中实例化该对象并将其添加到您的表单中。 In the form's constructor you could do this: 在表单的构造函数中,您可以执行以下操作:

var richTextBoxEx = new RichTextBoxEx();
// set your richTextBoxEx properties here
richTextBoxEx.Top = 100;
richTextBoxEx.Left = 100;

this.Controls.Add(richTextBoxEx);

While you could set properties as shown above, you also can do it (as you did) in the subclassed control's constructor. 尽管可以如上所述设置属性,但也可以在子类控件的构造函数中进行设置(就像以前一样)。

I hope this provides an alternative way to approach this. 我希望这提供了另一种解决方法。

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

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