构造函数中的C#set属性不是预期的vork

时间:2015-09-27 07:52:09

标签: c# visual-studio-2010 properties constructor 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);
    }
}

如您所见,水印未显示,构造函数WaterMarkTip值为NULL

enter image description here

但点击

后效果很好

enter image description here

我需要做些什么来解决这个问题?

VS 2010

1 个答案:

答案 0 :(得分:1)

您正在将构造函数初始值设定项混合使用。这条线

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

等同于此类

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;

如您所见,Watermark属性是在构造函数调用(第一行)之后分配的。 如果你在构造函数中需要它,那么使用参数

创建一个构造函数
public WaterMarkTextBox(string watermark)
{
    Watermark = watermark;
    // ...
}

或处理Watermark属性设置器。

编辑:根据您的评论,我发现您仍然不明白。好的,所以你的原始代码实际上是一个构造函数调用+属性赋值

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

注意()之前的{ - 这是实际的构造函数调用,只是C#允许省略(但仍然存在)。如果您按照建议更改构造函数,那么该行将变为

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

但请注意编辑前的答案的最后部分

  

或处理Watermark属性设置器。

属性设置器不仅用于设置支持字段。您遇到的问题是由Watermark属性设置器的错误实现引起的。因此,ether使它只读(删除setter)并将值传递给构造函数,或者,如果它确实需要读写,则保持无参数构造函数并正确实现setter。像这样的东西

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