简体   繁体   English

如果背景已更改,文本框不使用只读颜色

[英]TextBox Not using Readonly color if background has been changed

It seems that when you set the BackColor of a TextBox, Readonly ceases to affect the BackColor from then on.似乎当您设置 TextBox 的 BackColor 时,Readonly 从那时起不再影响 BackColor。 I have user control where, a decoration engine tracks validation, and highlights textboxes a certain color when the value has been validated.我有用户控制,装饰引擎跟踪验证,并在验证值时以某种颜色突出显示文本框。 However, once I've assigned Color.Yellow or SystemColors.Window to the TextBox.BackColor, setting TextBox.Readonly does nothing.但是,一旦我将 Color.Yellow 或 SystemColors.Window 分配给 TextBox.BackColor,设置 TextBox.Readonly 就什么也不做。

This is extremely easy to reproduce:这非常容易重现:

        public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }



        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.ReadOnly = !textBox1.ReadOnly;
        }


        private void button2_Click(object sender, EventArgs e)
        {
            textBox2.ReadOnly = !textBox2.ReadOnly;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            textBox2.BackColor = Color.Blue;
        }

        private void textBox1_ReadOnlyChanged(object sender, EventArgs e)
        {
            label1.Text = $"Readonly: {textBox1.ReadOnly}{Environment.NewLine}Color: {textBox1.BackColor}";
        }

        private void textBox2_ReadOnlyChanged(object sender, EventArgs e)
        {
            label2.Text = $"Readonly: {textBox2.ReadOnly}{Environment.NewLine}Color: {textBox2.BackColor}";
        }

        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(138, 286);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 1;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(219, 286);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(75, 23);
            this.button2.TabIndex = 3;
            this.button2.Text = "button2";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(300, 286);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(75, 23);
            this.button3.TabIndex = 4;
            this.button3.Text = "button3";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(108, 190);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(100, 22);
            this.textBox1.TabIndex = 5;
            this.textBox1.ReadOnlyChanged += new System.EventHandler(this.textBox1_ReadOnlyChanged);
            // 
            // textBox2
            // 
            this.textBox2.Location = new System.Drawing.Point(308, 190);
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(100, 22);
            this.textBox2.TabIndex = 6;
            this.textBox2.ReadOnlyChanged += new System.EventHandler(this.textBox2_ReadOnlyChanged);
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(105, 215);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(76, 17);
            this.label1.TabIndex = 7;
            this.label1.Text = "Readonly: ";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(305, 215);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(72, 17);
            this.label2.TabIndex = 8;
            this.label2.Text = "Readonly:";
            // 
            // Form1
            // 
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.textBox2);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.button3);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

#endregion
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
    }

Simply run that form, click button1 and button2 repeatedly, and both textboxes will cycle from default Window to Control background colors as the readonly property changes.只需运行该表单,重复单击 button1 和 button2,随着只读属性的更改,两个文本框将从默认窗口循环到控制背景颜色。 Button3, sets the textbox2 backcolor to Blue, and from then on, clicking button2 has no affect on the backcolor. Button3,将textbox2的背景色设置为蓝色,从那时起,点击button2对背景色没有任何影响。

I Do NOT want this behavior.我不想要这种行为。 I want to affect the backcolor, but I want readonly to supersede any custom backcolor i have assigned.我想影响背景色,但我希望 readonly 取代我分配的任何自定义背景色。

How do i achieve this?我如何实现这一目标?

Your question as I understand it is how to achieve a visual state where the textbox color uses the default value of SystemColors.Control when the TextBox is in the ReadOnly state and a different custom color when it's not.据我了解,您的问题是如何实现一种视觉状态,其中文本框颜色在TextBox处于ReadOnly状态时使用SystemColors.Control的默认值,而在非只读状态时使用不同的自定义颜色。

The easiest way I know of to do that is to handle the ReadOnlyChanged event of the TextBox controls.我知道的最简单的方法是处理TextBox控件的ReadOnlyChanged事件。 For example:例如:

public Form1()
{
    InitializeComponent();
    textBox2.ReadOnlyChanged += (sender, e) =>
    {
        textBox2.BackColor = textBox2.ReadOnly ? SystemColors.Control : Color.Blue;
    };
}

and also checking the state first when you set the custom background color:并在设置自定义背景颜色时首先检查状态:

private void button3_Click(object sender, EventArgs e)
{
    textBox2.BackColor = textBox2.ReadOnly ? SystemColors.Control : Color.Blue;
}

Well, apparently, because of "reasons", there is not "slick" way to achieve this, but i did find that if you set the BackColor = Color.Empty, the readonly behavior returns.好吧,显然,由于“原因”,没有“巧妙”的方式来实现这一点,但我确实发现如果你设置 BackColor = Color.Empty,只读行为会返回。 THis is due to the unchangeable code in TextBoxBase:这是由于 TextBoxBase 中不可更改的代码:

       public override Color BackColor {
        get {
            if (ShouldSerializeBackColor()) {
                return base.BackColor;
            }
            else if (this.ReadOnly) {
                return SystemColors.Control;
            } else {
                return SystemColors.Window;
            }
        }
        set {
            base.BackColor = value;
        }
    }

The ShouldSerializeBackColor() will return false if you set the backcolor to Color.Empty, allowing the second part of that if-else condition to process, and voila.如果将背景色设置为 Color.Empty,ShouldSerializeBackColor() 将返回 false,从而允许处理 if-else 条件的第二部分,瞧。 It ain't pretty, but at least it works.它不漂亮,但至少它有效。

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

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