【问题标题】:C# Custom Control's attribute not initialized after InitializeComponent() call?调用 InitializeComponent() 后 C# 自定义控件的属性未初始化?
【发布时间】:2020-08-29 11:36:47
【问题描述】:

我正在尝试创建一个简单的文本框,该文本框在未获得焦点且文本为空时显示提示文本,并在获得焦点时隐藏提示文本。为此,我通过扩展 TextBox 创建了一个自定义控件。

public partial class HintedTextBox : TextBox
{
    private Color foreColor;

    public HintedTextBox()
    {
        InitializeComponent();
        foreColor = ForeColor;
        GotFocus += OnFocused;
        LostFocus += OnFocusLost;

        OnFocusLost(null, null); // Problem
    }

    public string Hint { get; set; }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    private void OnFocused(object sender, EventArgs e)
    {
        if (Text == Hint)
        {
            Text = "";
            ForeColor = foreColor;
        }
    }

    private void OnFocusLost(object sender, EventArgs e)
    {
        if (Text.Trim() == "") 
        {
            Text = Hint;
            ForeColor = Color.Gray;
        }
        else
        {
            ForeColor = foreColor;
        }
    }
}

从逻辑上讲,我需要在组件初始化后调用OnFocusLost() 过程,以便应用程序在首次显示表单时显示提示。问题出在我用// problem 标记的那一行。在这一行,我的自定义属性Hint 和库存属性Text 都没有初始化,即使我已经在设计器中设置了它们的值。奇怪的是ForeColor 属性已经在该行初始化。是否有其他事件在这些值初始化后立即触发,或者是否有其他解决方案?

我还尝试从 Windows 窗体的 FormLoad 事件的控件外部调用 OnFocusLost()。它也不起作用。 TextHint 在开始时总是空的,即使在 InitializeComponent() 调用之后也是如此。

感谢您的关注。

编辑: 我忘记将表单的加载事件附加到我的 FormLoad() 方法中,但 Vladimir Stoyanov 的解决方案非常有效,甚至更好。

【问题讨论】:

  • 定义“初始化”。这些属性肯定会被初始化,因为这是一个基本的 C# 功能。不过,它们可能只被初始化为其默认值。如果您期望它们被初始化为其他值,通常会在InitializeComponent() 方法用于包含对象 中处理,即Form 子类。自然,该代码还不能在这里执行,因为构造函数还没有返回。如果您希望在设置 Hint 时引发事件,则由您来实现。 ...
  • ... 您继承的 Text 属性已经有一个 TextChanged 事件。您根本没有发布任何InitializeComponent() 方法,更不用说期望这些属性被初始化的任何代码,因此任何人都不可能正确回答您的问题。请参阅minimal reproducible exampleHow to Ask
  • 听起来你想要文本框的水印? stackoverflow.com/questions/18497130/watermark-for-textbox/…
  • @PeterDuniho "Initialized" 如中,如果我设置了 Hint 属性,比方说“搜索”,来自设计器,它应该在 InitializeComponent() 之后具有值“搜索”,但是它是空的。文本,即使我已经从设计器中设置了它的值,在 InitializeComponent() 之后仍然在构造函数中保留“”。
  • @PeterDuniho 为什么我需要发布 InitializeComponent() 的内容?它由 Visual Studio 自动生成。我应该再发 100 行吗?

标签: c# winforms custom-controls windows-forms-designer


【解决方案1】:

作为一个选项,您可以只使用 Hint 属性的 setter。当您以后需要以编程方式更改提示时,它将处理这种情况

private string hint;
public string Hint
{
    get => hint;
    set
    {
        hint = value;
        OnFocusLost(null, null);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 2018-12-02
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    相关资源
    最近更新 更多