为什么我的自定义用户控件不会引发鼠标事件?

为什么我的自定义用户控件不会引发鼠标事件?

问题描述:

我想创建一个组合自定义控件,其中包含将由某些客户端表单使用的跟踪栏和其他控件。我需要公开一些事件,如MouseDownMouseUp以检测拖动的开始和拖动的结束。奇怪的是,MouseDown是好的,但不是MouseUp。下面的代码演示了它。这是.NET Framework或trackbar中的错误吗?如果不是,我应该怎么做呢?为什么我的自定义用户控件不会引发鼠标事件?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Data; 
using System.Text; 
using System.Windows.Forms; 

namespace MyTrackbar 
{ 

    public partial class UserControl1 : UserControl 
    { 
     public delegate void StartDragHandler(); 
     public delegate void EndDragHandler(); 

     [Category("Action")] 
     [Description("Fires when user starts to drag.")] 
     public event StartDragHandler StartDrag; 
     [Category("Action")] 
     [Description("Fires when user ends to drag.")] 
     public event EndDragHandler EndDrag; 

     public UserControl1() 
     { 
      InitializeComponent(); 
     } 

     private void trackBar1_MouseDown(object sender, MouseEventArgs e) 
     { 
      textBox1.BackColor = Color.Red; 
      if (StartDrag != null) { 
       StartDrag(); 
      } 

     } 

     private void trackBar1_MouseUp(object sender, MouseEventArgs e) 
     { 
      textBox1.BackColor = Color.White; 
      if (EndDrag != null) { 
       EndDrag(); 
      } 
     } 
    } 
} 



using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 

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

     private void userControl11_StartDrag() 
     { 
      // Work 
      textBox1.BackColor = Color.Red; 
     } 

     private void userControl11_MouseUp(object sender, MouseEventArgs e) 
     { 
      // Doesn't work !!!!!!!!!!!! 
      textBox1.BackColor = Color.White; 
     } 
    } 
} 

更新:对于谁需要检查InitializeComponent人,即使我没有修改它:

对于自定义控制:

namespace MyTrackbar 
{ 
    partial class UserControl1 
    { 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Component Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.trackBar1 = new System.Windows.Forms.TrackBar(); 
      this.textBox1 = new System.Windows.Forms.TextBox(); 
      ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit(); 
      this.SuspendLayout(); 
      // 
      // trackBar1 
      // 
      this.trackBar1.Location = new System.Drawing.Point(21, 17); 
      this.trackBar1.Name = "trackBar1"; 
      this.trackBar1.Size = new System.Drawing.Size(356, 45); 
      this.trackBar1.TabIndex = 0; 
      this.trackBar1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trackBar1_MouseDown); 
      this.trackBar1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.trackBar1_MouseUp); 
      // 
      // textBox1 
      // 
      this.textBox1.Location = new System.Drawing.Point(31, 68); 
      this.textBox1.Name = "textBox1"; 
      this.textBox1.Size = new System.Drawing.Size(338, 20); 
      this.textBox1.TabIndex = 1; 
      // 
      // UserControl1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.Controls.Add(this.textBox1); 
      this.Controls.Add(this.trackBar1); 
      this.Name = "UserControl1"; 
      this.Size = new System.Drawing.Size(400, 150); 
      ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit(); 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     private System.Windows.Forms.TrackBar trackBar1; 
     private System.Windows.Forms.TextBox textBox1; 
    } 
} 

对于WinForm的客户端:

namespace TestMyTrackBar 
{ 
    partial class Form1 
    { 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.userControl11 = new MyTrackbar.UserControl1(); 
      this.textBox1 = new System.Windows.Forms.TextBox(); 
      this.SuspendLayout(); 
      // 
      // userControl11 
      // 
      this.userControl11.Location = new System.Drawing.Point(13, 39); 
      this.userControl11.Name = "userControl11"; 
      this.userControl11.Size = new System.Drawing.Size(400, 114); 
      this.userControl11.TabIndex = 0; 
      this.userControl11.StartDrag += new MyTrackbar.UserControl1.StartDragHandler(this.userControl11_StartDrag); 
      this.userControl11.MouseUp += new System.Windows.Forms.MouseEventHandler(this.userControl11_MouseUp); 
      // 
      // textBox1 
      // 
      this.textBox1.Location = new System.Drawing.Point(45, 160); 
      this.textBox1.Name = "textBox1"; 
      this.textBox1.Size = new System.Drawing.Size(336, 20); 
      this.textBox1.TabIndex = 1; 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(457, 231); 
      this.Controls.Add(this.textBox1); 
      this.Controls.Add(this.userControl11); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     private MyTrackbar.UserControl1 userControl11; 
     private System.Windows.Forms.TextBox textBox1; 
    } 
} 
+0

你实际上是在使用'TrackBar'控件,还是建立了自己的自定义滑块? – 2010-12-10 16:58:57

+1

你说得对,我只是意识到,当我将轨迹栏嵌入到自定义控件中时,它不起作用。 – user310291 2010-12-11 10:57:56

+0

@ user310291如果它不起作用,它不能成为框架错误。如果是这样,.NET框架应该比它的SLOC计数有更多的错误! – Luca 2010-12-11 18:08:40

private void userControl11_MouseUp(object sender, MouseEventArgs e) 
    { 
     // Doesn't work !!!!!!!!!!!! 
     textBox1.BackColor = Color.White; 
    } 

Y你应该使用EndDrag事件,而不是MouseUp。

+0

抱歉,我太累了,那一天,我没有看到我明显的错误:) – user310291 2010-12-14 23:04:37

目前还不清楚真正的问题,因为InitializeComponent的实现完全从示例中丢失。

所以,我的回答是基于以下断言:

  • UserControl1.trackBar1的TrackBar,* trackBar1_MouseDown *是UserControl1.trackBar1.MouseDown的subsciber,* trackBar1_MouseUp *是UserControl1.trackBar1.MouseUp
  • Form1.userControl11的subsciber是的UserControl1,* userControl11_StartDrag()*是Form1.userControl11.StartDrag事件的订户,* userControl11_MouseUp *是Form1.userControl11.MouseUp事件

这是正确的, “不工作” 的用户。可能(如果是的话,你应该确认)事件Form1.userControl11.MouseUp永远不会被引发。 Infact Form1.userControl11.MouseUp and UserControl1.trackBar1.MouseUp不一样; INFACT 的UserControl1类暴露EndDrag事件当其嵌入控制trackBar1引发的MouseUp事件。

因此,解决方案是订阅UserControl1.EndDrag事件,而不是鼠标向上(如Hans Passant所述),以反映正确的行为(我认为)。

+0

没有什么特别的InitializeComponent这就是为什么我没有发布它。现在,我可以发布它,如果你想确保没有错。 – user310291 2010-12-11 18:50:17

+0

“解决方案是订阅EndDrag事件”:这是不可能的,因为Trackbar控件不存在此事件,或者我错过了什么? – user310291 2010-12-11 18:56:29

+0

EndDrag事件在UserControl1类中声明,它不是一个TrackBar。然而,重读汉斯帕斯坦的回答和评论,我的回答完全一样。 – Luca 2010-12-11 22:43:02

在开始之前,我想澄清一下answer provided by Hans Passant已经解释了我正要做的事情。所以,如果你觉得这有帮助,你应该提出他的答案。

但是,从评论交流看来,你并不完全明白他想说什么。也许我可以更好地解释它,也许如果你明白你在代码中改变了什么,如果了解发生了什么,你会更容易。

让我们从评估当前情况开始:当用户开始拖动轨迹条时,属于userControl11的文本框会正确更改颜色。但是,在完成拖动轨迹条后,作为Form1一部分的第二个文本框不会变回白色。

您的用户控件已经引发了两个自定义事件StartDragEndDrag,其中的名称显然表示当前状态。在Form1中,您正在处理用户控件的StartDrag事件并将第二个文本框的颜色更改为红色。但是,不是处理EndDrag事件以将颜色更改为白色,而是处理MouseUp事件。这就是为什么它不起作用,汉斯的回答是想告诉你什么。 相反,你的窗体的代码看起来应该是这样:

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

     this.userControl11.EndDrag += new MyTrackbar.UserControl1.EndDragHandler(this.userControl11_EndDrag); 
    } 

    private void userControl11_StartDrag() 
    { 
     // Works 
     textBox1.BackColor = Color.Red; 
    } 

    private void userControl11_EndDrag() 
    { 
     // Now also works! 
     textBox1.BackColor = Color.White; 
    } 
} 

你已经明白你需要处理你提的定制StartDrag事件,因此它似乎很简单,你最好也需要来处理事件以达到预期的效果。

但是,你可能会问,“为什么MouseUp事件在用户控件里面工作,但是不是工作在窗体里面?!?”我认为这是你试图争论的是.NET Framework中的一个错误。 (提示:这是不太可能,任何人都会发现在框架真正的bug比我们中的一个困惑为什么我们看到,我们的行为,或者只是缺少明显的东西。)

原因是因为在用户控件内部,您正在处理trackbar控件(trackBar1)引发的MouseUp事件。 但该事件不会向上传播。仅仅因为trackbar控件引发了MouseUp事件,而不是意味着包含它的用户控件引发同一事件。您似乎已经知道,关于MouseDown事件,与MouseUp事件完全相同。

不需要向微软提交错误报告,也不需要任何人让自己的感受受到伤害。