简体   繁体   English

构造函数中的C#set属性未按预期顺序

[英]C# set property in constructor not vork as expected

I try use textbox with watermark 我尝试使用带有水印的文本框

public partial class ModernBox : Form
{
    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HT_CAPTION = 0x2;

    [DllImportAttribute("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    [DllImportAttribute("user32.dll")]
    public static extern bool ReleaseCapture();

    private const int WM_NCHITTEST = 0x84;
    private const int HTCLIENT = 0x1;
    private const int HTCAPTION = 0x2;

    static Color ColorMain = Color.FromArgb(42, 42, 44);
    static Color ColorTransparent = Color.Transparent;

    Panel p_bro = new Panel{Visible = false};
    Panel p_auth = new Panel{Visible = false};
    WaterMarkTextBox textBox1;// = new WaterMarkTextBox{Location = new Point(10,40),Visible = true,Width = 200};
    WaterMarkTextBox textBox2 = new WaterMarkTextBox{

    Location = new Point(10,70),Visible = true,Width = 200,WaterMark = "123"};

    protected override void WndProc(ref Message message)
    {
        base.WndProc(ref message);

        if (message.Msg == WM_NCHITTEST && (int)message.Result == HTCLIENT)
            message.Result = (IntPtr)HTCAPTION;
    }

    public ModernBox()
    {
      InitializeComponent();

      panel1.MouseMove += (o, e) => {
                if (e.Button == MouseButtons.Left) {
                    ReleaseCapture();
                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                }
            };

      panel1.BackColor = ColorMain;

      this.StartPosition = FormStartPosition.CenterScreen;
      this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
      this.Width = 600;
      this.Height = 400;

      p_bro.Controls.Add(Program.presentation.webBrowser1); 
      Program.presentation.webBrowser1.Location = new Point(10,-70);
      Program.presentation.webBrowser1.Height = 560;
      p_bro.Location = new Point(0,30);

      //this.Focus();
      this.textBox1 = new WaterMarkTextBox{Location = new Point(10,40),Visible = true,Width = 400,WaterMark = "mark",Tip = "tip"};
      this.textBox1.PerformLayout();
      //textBox1.WaterMark = "wm1";
      //textBox1.Tip = "tip1";

      this.Controls.Add(p_bro); 
      this.Controls.Add(p_auth);
      this.Controls.Add(this.textBox1);
      this.Controls.Add( textBox2);

      //ModeAuth();
      //ModeBro();
    }

    public void ModeBro()
    {
        p_auth.Hide();
        p_bro.Show();

        Program.presentation.webBrowser1.BringToFront();

        p_bro.MouseHover += (o, e) => { Program.presentation.webBrowser1.Focus(); };
        p_bro.AutoScroll = false;
        p_bro.HorizontalScroll.Enabled = false;
        p_bro.HorizontalScroll.Visible = false;
        p_bro.Width = Program.presentation.webBrowser1.Width;
        p_bro.Height = Program.presentation.webBrowser1.Height-50;

        this.Width = p_bro.Width;//Program.presentation.webBrowser1.Width; 
        this.Height = p_bro.Height-5;//Program.presentation.webBrowser1.Height-20;
    }

    public void ModeAuth()
    {
        p_bro.Hide();
        p_auth.Show();

        this.Width = 600;
        this.Height = 400;
    }

    private void BtnClose_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void BtnMaximize_Click(object sender, EventArgs e)
    {
      if(this.WindowState != FormWindowState.Minimized)
        this.WindowState = FormWindowState.Maximized;
      else 
        this.WindowState = FormWindowState.Normal;
    }

    private void BtnMinimaze_Click(object sender, EventArgs e)
    {
      this.WindowState = FormWindowState.Minimized;
    }
}

public class WaterMarkTextBox : TextBox
{
    ToolTip TTip = new ToolTip();

    private string _WaterMark;
    public string WaterMark
    {
        get { return _WaterMark; }
        set { _WaterMark = value; }
    }

    private string _Tip;
    public string Tip
    {
        get { return _Tip; }
        set { _Tip = value; }
    }

    public WaterMarkTextBox()
    {
        this.ForeColor = SystemColors.GrayText;
        //if(WaterMark==null) MessageBox.Show("fail");

        this.Text = _WaterMark;
        this.Leave += new System.EventHandler(this._Leave);
        this.Enter += new System.EventHandler(this._Enter);
        this.MouseHover += new EventHandler(WaterMarkTextBox_MouseHover);
    }

    private void _Leave(object sender, EventArgs e)
    {
        if (this.Text.Length == 0)
        {
            this.Text = _WaterMark;
            this.ForeColor = SystemColors.GrayText;
        }
    }

    private void _Enter(object sender, EventArgs e)
    {
        //MessageBox.Show(_WaterMark);
        if (this.Text == _WaterMark)
        {
            this.Text = "";
            this.ForeColor = SystemColors.WindowText;
        }
    }

    private void WaterMarkTextBox_MouseHover(object sender, EventArgs e)
    {
        if (Tip != null)
            TTip.Show(Tip, this, 0, (int)(this.Height * 1.2), 2000);
    }
}

As you can see watermark not appear, in constructor WaterMark and Tip value are NULL . 如您所见,没有出现水印,在构造函数中, WaterMarkTip值为NULL

在此处输入图片说明

But it works fine after click 但是点击后它可以正常工作

在此处输入图片说明 .

What do I need to do to fix this? 我需要做什么来解决这个问题?

VS 2010 VS 2010

You are mixing the constructor with initializer . 您正在将构造函数initializer混合使用。 The line 线

this.textBox1 = new WaterMarkTextBox{Location = new Point(10,40),Visible = true,Width = 400,WaterMark = "mark",Tip = "tip"};

is equivalent to something like this 相当于这样的东西

var temp = new WaterMarkTextBox();
temp.Location = new Point(10,40);
temp.Visible = true;
temp.Width = 400;
temp.WaterMark = "mark";
temp.Tip = "tip";
this.textBox1 = temp;

As you can see, the Watermark property is assigned after the constructor call (the first line). 如您所见, Watermark属性是在构造函数调用之后分配的(第一行)。 If you need it inside the constructor, then make a constructor with parameters 如果需要在构造函数中使用它,请使用参数来构造一个构造函数

public WaterMarkTextBox(string watermark)
{
    Watermark = watermark;
    // ...
}

or handle the Watermark property setter. 或处理Watermark属性设置器。

EDIT: From your comment I see you still don't understand. 编辑:从您的评论,我看到您仍然不了解。 Ok, so your original code is actually a constructor call + property assignments 好的,所以您的原始代码实际上是一个构造函数调用+属性分配

this.textBox1 = new WaterMarkTextBox() {Location = new Point(10,40),Visible = true,Width = 400,WaterMark = "mark",Tip = "tip"};

Note the () before the { - this is the actual constructor call, just C# allows to omit that (but still it's there). 请注意{之前的() -这是实际的构造函数调用,只是C#允许忽略它(但仍然存在)。 If you change the constructor like suggested, that line becomes 如果像建议的那样更改构造函数,则该行将变为

this.textBox1 = new WaterMarkTextBox("mark") {Location = new Point(10,40),Visible = true,Width = 400,Tip = "tip"};

But note the last part of my answer before the edit 但是在编辑之前请注意我答案的最后一部分

or handle the Watermark property setter. 或处理Watermark属性设置器。

Property setters are not just for setting the backing fields. 属性设置器不仅用于设置后备字段。 The problem you are experiencing is caused by the incorrect implementation of your Watermark property setter. 您遇到的问题是由Watermark属性设置器的错误实现引起的。 So, ether make it read only (remove the setter) and pass the value to the constructor, or, if it really needs to be read write, then keep the parameterless constructor and implement the setter correctly. 因此,ether将其设置为只读(删除setter)并将其值传递给构造函数,或者,如果确实需要将该值传递给构造函数,则保留无参数构造函数并正确实现setter。 Something like this 像这样

public class WaterMarkTextBox : TextBox
{
    ToolTip TTip = new ToolTip();

    private string _WaterMark = string.Empty;
    public string WaterMark
    {
        get { return _WaterMark; }
        set
        {
            if (value == null) value = string.Empty;
            if (_WaterMark == value) return;
            _WaterMark = value;
            if (this.DesignMode || this.ContainsFocus) return;
            this.Text = _WaterMark;
            this.ForeColor = SystemColors.GrayText;
        }
    }

    private string _Tip;
    public string Tip
    {
        get { return _Tip; }
        set { _Tip = value; }
    }

    public WaterMarkTextBox()
    {
        this.Leave += new System.EventHandler(this._Leave);
        this.Enter += new System.EventHandler(this._Enter);
        this.MouseHover += new EventHandler(WaterMarkTextBox_MouseHover);
    }

    private void _Leave(object sender, EventArgs e)
    {
        if (this.Text.Length == 0)
        {
            this.Text = _WaterMark;
            this.ForeColor = SystemColors.GrayText;
        }
    }

    private void _Enter(object sender, EventArgs e)
    {
        if (this.Text == _WaterMark)
        {
            this.Text = "";
            this.ForeColor = SystemColors.WindowText;
        }
    }

    private void WaterMarkTextBox_MouseHover(object sender, EventArgs e)
    {
        if (Tip != null)
            TTip.Show(Tip, this, 0, (int)(this.Height * 1.2), 2000);
    }
}

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

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