日期:2014-05-17  浏览次数:21095 次

C#:Control控件里的ComboBox在设计视图下焦点可以进入的解决办法

上一篇博客里说到,当我们编写一个控件直接继承于Control,并且里面Add了一个ComboBox的时候的问题。

今天继续接着这个说。


有的人可能会觉得奇怪,自定义控件不是直接新建一个UserControl就好了吗,干嘛用代码直接写,直接继承Control?

这个我就不多说了,总之制作自定义控件不光可以使用UserControl。有的时候用Control会更好一些。


那么今天的问题是,当我们按照以下的代码写了一个控件,并且将之拖到到窗体上的时候,我们会发现。

即使在设计试图下(还没有运行程序的时候),我们的鼠标也依然可以直接点进这个Control里的ComboBox。并且还可以用键盘输入值。

这个是非常诡异的一个表现,如果你是要做控件给别人用的话,这个现象就会显示出你不够专业。


示例代码:

 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Windows.Forms;
 using System.Data;
 using System.ComponentModel;
 
 namespace WindowsFormsApplication1
 {
     public class TestComboBox : Control
     {
         private ComboBox m_combo;
         public Control GetInnerControl()
         {
             return m_combo;
         }
         public TestComboBox()
         {
             //创建一个comboBox
             m_combo = new ComboBox();
             m_combo.Size = new System.Drawing.Size(100, 20);
             m_combo.Location = new System.Drawing.Point(0, 0);
             m_combo.FormattingEnabled = true;
             m_combo.Name = "comboBox1";
             m_combo.TabIndex = 0;
 
             //构造用于绑定到comboBox的DataSource的假数据
             DataTable table = new DataTable();
             table.Columns.Add("code");
             table.Columns.Add("name");
 
             table.Rows.Add("1", "AA");
             table.Rows.Add("2", "BB");
 
             //设定绑定方式
             m_combo.DataSource = table;
             m_combo.DisplayMember = "name";
             m_combo.ValueMember = "code";
 
             this.Controls.Add(m_combo);
         }
     }
 }
 


嗯,非常神奇的一个效果。但是这并不是我们想要的。

该怎么解决这个问题呢?


这个是属于设计视图下的问题,对程序实际运行起来之后,并没有什么影响。

所以我们该从设计器下手,替换掉微软默认的设计器。


我们为这个TestComboBox类指定一个设计器。

添加

[Designer(typeof(TestDesigner))]

这句代码到类名的上一行。

如下:


 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Windows.Forms;
 using System.Data;
 using System.ComponentModel;
 
 namespace WindowsFormsApplication1
 {
     [Designer(typeof(TestDesigner))]
     public class TestComboBox : Control
     {
         private ComboBox m_combo;
         public Control GetInnerControl()
         {
             return m_combo;
         }
...

然后在项目里确认是否有System.Design的引用。


接着,新建一个类,写下如下代码:

 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Windows.Forms;
 using System.ComponentModel;
 
 namespace WindowsFormsApplication1
 {
     public class TestDesigner : System.Windows.Forms.Design.ControlDesigner
     {
         Control mask = new Control();
 
         public override void Initialize(IComponent component)
         {
             base.Initialize(component);
 
             if (this.Control is TestComboBox)
             {
                 Control p = mask.Parent;
                 mask.Parent = (this.Control as TestComboBox).GetInnerControl();
             }
         }
 
         protected override void OnPaintAdornments(PaintEventArgs pe)
         {
             base.OnPaintAdornments(pe);
 
             if (this.Control is TestComboBox)
             {
                 if ((this.Control as TestComboBox).GetInnerControl().Enabled == false)
                 {
                     mask.Dispose();
                 }
             }
         }
     }
 }
 

这样,我们就继承了设计器,并且自己写了一个设计器。

然后将控件的设计器指定成它。


现在编译,关掉窗体设计视图,再打开

现在是不是已经不会让焦点进去其中了呢?


转摘请注明出处