问题
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. 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.
回答1:
The property values which you set in constructor of the control are usually respected. But for Text
property, the case is a bit different. 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
.
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. Then after calling base method, set the Text
property again to the default value.
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.
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. For example for AutoSize
property of the Label
.
回答2:
The Text
property gets reseted upon InitializeComponent
of the Form.
When you have a look at the Designer.cs
file of the Form
you should find a line like the following:
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
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:
The OnCreateControl method is called when the control is first created
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();
}
}
回答3:
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. 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).
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.
回答4:
It wasn't clear to me how you were instantiating the RichTextBox, so this might or might not be useful...
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. If you had done that, then you would be getting an instance of RichTextBox and not RichTextBoxEx.
To get an instance of RichTextBoxEx, you could compile it to a DLL and add it to your toolbox.
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.
来源:https://stackoverflow.com/questions/54636332/changing-an-extended-richtextbox-text-in-constructor-doesnt-work