返回首页

|:在下拉复选框的OwnerDraw的ComboBox{S0}简介
我需要添加过滤列表视图。列表视图已经有了一个ToolStrip,我可以添加相应的部件。我决定转项目的下拉组合框与复选框和关闭是最节省空间,并直观的方式来实现它。然而,这需要一个所有者绘制的ComboBox。幸运的是,。NET 2.0框架,包括一个辅助类,CheckBoxRenderer,给予正确的参数为您呈现的下拉列表"复选框,。使用代码
第一步是继承System.Windows.Forms.ComboBox类:

public partial class CheckComboBox : ComboBox

{

    public CheckComboBox()

    {

        this.DrawMode = DrawMode.OwnerDrawFixed;

        ...

    }



    ...

}

请注意,我设置DrawMode属性告诉ComboBox中,我们打算自己呈现下拉列表项。下一步是定义一个类来包含我们的下拉列表项的数据,​​并保持状态。这是一个简单的类:{C}
然后我们线ComboBox的DrawItem事件的委托:
this.DrawItem += new DrawItemEventHandler(CheckComboBox_DrawItem);

和实施如下:
void CheckComboBox_DrawItem( object sender, DrawItemEventArgs e )

{

    if (e.Index == -1)

    {

        return;

    }



    if( !( Items[ e.Index ] is CheckComboBoxItem ) )

    {

        e.Graphics.DrawString( 

            Items[ e.Index ].ToString(), 

            this.Font, 

            Brushes.Black, 

            new Point( e.Bounds.X, e.Bounds.Y ) );

        return;

    }



    CheckComboBoxItem box = (CheckComboBoxItem)Items[ e.Index ];



    CheckBoxRenderer.RenderMatchingApplicationState = true;

    CheckBoxRenderer.DrawCheckBox( 

        e.Graphics, 

        new Point( e.Bounds.X, e.Bounds.Y ), 

        e.Bounds, 

        box.Text, 

        this.Font, 

        ( e.State & DrawItemState.Focus ) == 0, 

        box.CheckState ? CheckBoxState.CheckedNormal : 

            CheckBoxState.UncheckedNormal );

}

在此委托,我们首先要做的是验证我们所提供的该项目是作为CheckComboBoxItem添加。如果不是,我们呈现它作为一个简单的字符串。否则,我们得到适当CheckComboBoxItem从Items集合(使用DrawItemEventArgs.Index属性)。然后我们调用CheckBoxRenderer.DrawCheckBox()方法,传递的Graphics对象,我们要呈现复选框,位置,大小,文字,字体,重点和检查的国家。
的结果是,它会使我们的下拉列表中的项目,看起来像复选框:{S0}
下一步,我们要检查状态切换时被选中的项目之一。因此,我们线另一位代表,但这次SelectedIndexChanged事件:
this.SelectedIndexChanged += 

    new EventHandler( CheckComboBox_SelectedIndexChanged );

和实施如下:
void CheckComboBox_SelectedIndexChanged( object sender, EventArgs e )

{

    CheckComboBoxItem item = (CheckComboBoxItem)SelectedItem;

    item.CheckState = !item.CheckState;

    ...

}

这使得我们在下拉式切换"复选框,但不允许该控制的用户知道发生了什么。所以,我们还添加了一个公共事件,以通知控制的用户在下拉列表中改变一个项目的检查状态:
public event EventHandler CheckStateChanged;

和我们消防此事件,当我们切换上面的状态,因此,完整的方法看起来像这样:
void CheckComboBox_SelectedIndexChanged( object sender, EventArgs e )

{

    CheckComboBoxItem item = (CheckComboBoxItem)SelectedItem;

    item.CheckState = !item.CheckState;

    if (CheckStateChanged != null)

        CheckStateChanged(item, e);

}
使用控制
要使用的控制,你只需将其添加到您所选择的容器,并添加像这样的项目:
checkComboBox1.Items.Add(new CheckComboBox.CheckComboBoxItem("One", true));

checkComboBox1.Items.Add(new CheckComboBox.CheckComboBoxItem("Two", true));

checkComboBox1.Items.Add(new CheckComboBox.CheckComboBoxItem("Three", true));

为了得到检查状态已被用户修改的通知:
this.checkComboBox1.CheckStateChanged += 

    new EventHandler(this.checkComboBox1_CheckStateChanged);

可以这样处理:
private void checkComboBox1_CheckStateChanged(object sender, EventArgs e)

{

    if (sender is CheckComboBox.CheckComboBoxItem)

    {

        CheckComboBox.CheckComboBoxItem item = 

            (CheckComboBox.CheckComboBoxItem)sender;

        ... 

    }

}
完成的示例应用程序

回答

评论会员:游客 时间:2011/12/14
嗨,像我每次下载的代码似乎,它只有在VS2010中打开,但我们使用VisualStudio2008。是否有可能获得的VS2008的源代码?在此先感谢,卡塔琳
德里克维尔容
评论会员:游客 时间:2011/12/14
只是创建一个空项目和现有的源文件手动添加项目。源代码是相同的。只有项目和解决方案的格式是不同的
。卡塔琳卡尔曼
评论会员:游客 时间:2011/12/14
感谢,imgsrc=http://www.orcode.com/upimg/2011_12_14_13_22_55_3.gif的工作
会员3854225
评论会员:游客 时间:2011/12/14
我不喜欢它:无效CheckComboBox_DrawItem(对象发件人,DrawItemEventArgs发送){  (e.Index==-1) {返回} 如果(!(项目[e.Index]是CheckComboBoxItem)) { TextRenderer.DrawText(e.Graphics项目[e.Index]的ToString(),this.Font, 新的点(e.Bounds.X,e.Bounds.Y), SystemColors.ControlText); 返回 }CheckComboBoxItem盒=(CheckComboBoxItem)项目[e.Index]CheckBoxRenderer.DrawCheckBox(e.Graphics,新点(e.Bounds.X1,e.Bounds.Y), box.CheckState?CheckBoxState.CheckedNormal:CheckBoxState.UncheckedNormal);TextRenderer.DrawText(e.Graphics,box.Text,this.Font,新点,e.Bounds.Y(e.Bounds.X15),SystemColors.ControlText);}净吨位;2.0正常工作。-WojtekG.
斯泰利奥斯Alexandrakis
评论会员:游客 时间:2011/12/14
一个问题,是对我来说非常重要,因为这是一个多选择,你知道如何使下拉列表中打开,直到用户点击或控制外折叠再次单击下拉按钮
?Massalla
评论会员:游客 时间:2011/12/14
嗨,我有同样的问题,我结束了写我自己的版本,解决了它。一看:{A}]。希望有帮助。imgsrc=http://www.orcode.com/upimg/2011_12_14_13_22_55_3.gif
德里克维尔容
评论会员:游客 时间:2011/12/14
嗨,我怎样才能使下拉保持开放的情况下,我想用户切换,而无需重新下拉一次又一次超过一个复选框?萨沙-4:02周五8月10日修改,2007年此外,我怎么能覆盖SelectedText?我试图设置SelectedText到一个逗号分隔的列表,选中复选框的文本,但没有奏效。
Massalla
评论会员:游客 时间:2011/12/14
萨沙,这是一个行为,可能会需要编写自己的自定义下拉控件。但是,如果按照本条第(约左对齐文本)"其他"的讨论主题,你会看到别人有同样的问题。有一些建议。
TasneemJ
评论会员:游客 时间:2011/12/14
噢......对不起,我想我错过了(虽然我读的线程一个实施左对齐劈)...{BR}但我仍然有问题,我不能设置SelectedText。的做法是错误的?我试图捕捉事件时下拉关闭通过复选框循环来收集所有检查项目的一个逗号分隔的字符串。然后,我会设置SelectedText属性的字符串值。但是这并没有出于某种原因。任何线索?我会进一步的细节后一些代码的明天,如果有必要]感谢...萨沙
德里克维尔容
评论会员:游客 时间:2011/12/14
喜关于您做注:"正确对齐文本,所以左对齐(需要找出如何计算复选框位图的宽度,以正确地做到这一点)"我真的想实现这个。如何去任何想法吗?{五}
TasneemJ
评论会员:游客 时间:2011/12/14
这里是一个破解的CheckComboBox_DrawItem方法:CheckBoxRenderer.DrawCheckBox(e.Graphics,新的点(e.Bounds.X,e.Bounds.Y),e.Bounds,"box.Text,this.Font,TextFormatFlags.Left, (e.StateDrawItemState.Focus)==0,box.CheckState?CheckBoxState.CheckedNormal:CheckBoxState.UncheckedNormal);要突出的变化,我增加了前导空格box.Text参数(移动到右侧),并添加TextFormatFlags.Left参数。这不是一个完美的解决方案,因为添加空格的数量取决于你使用的字体,如果您有任何的默认样式以外,您可以使用Graphics.MeasureString方法来计算它在飞,但是,同样,你需要知道确切的复选框位图的大小。这也可能发生变化,不同的视觉风格。-德里克维尔容
德里克维尔容
评论会员:游客 时间:2011/12/14
我试图确定复选框的宽度,但找不到任何信息。所以,我砍死它类似于你:CheckBoxRenderer.DrawCheckBox(e.Graphics, 新的点(e.Bounds.X,e.Bounds.Y),新的Rectangle(新点,e.Bounds.Y(e.Bounds.X13),新的大小(e.Bounds.Width,e.Bounds.Height))box.Text,this.Font,TextFormatFlags.Left,(e.StateDrawItemState.Focus)==0,box.CheckState?CheckBoxState.CheckedNormal:CheckBoxState.UncheckedNormal);imgsrc=http://www.orcode.com/upimg/2011_12_14_13_22_55_6.gif另一个问题,因为这是一个多选择,你知道如何保持打开下拉列表中,直到用户点击控制外,再次单击下拉按钮或折叠??与旧的C控制写在这里:http://www.codeproject.com/combobox/checkcombo.asp感谢您的输入。
pavvel
评论会员:游客 时间:2011/12/14
不,不关我的头顶但是,我没有类似的网格控件。我们希望能够用鼠标右键单击列标题,弹出一个可用列的列表,所以你可以通过检查该列表中的复选框隐藏/显示。我们只是做了一个FixedToolWindow与FormBorderStyle设置为浮动窗口,填入一个复选框列表。这已经足够好了,并在右上角的关闭"X"按钮,使用户可以关闭它,当他们完成。我们没有一个模态对话框(如果我记得没错),所以反馈是即时的(他们会检查框和列会立即出现,取消选中它,它就会消失)。(模态的一部分,重要的是保持在主UI线程,而你处理对话框反馈)-德里克维尔容
德里克维尔容
评论会员:游客 时间:2011/12/14
在那里我可以找到这一解决方案的源代码?最好的问候,帕维尔
约瑟夫Benikovsky
评论会员:游客 时间:2011/12/14
我怕我做了一个前雇主,并没有访问该代码。(坦率地说,即使我知道我会不会能够分享它,因为它在技术上是他们的IP)。我有点短的时间,现在砍你。这真的不难虽然。我想创建一个窗体来保存列表,设置的形式显示属性使用一个工具框的边框样式。显示的ShowDialog(),而不是只显示(),和你业务。
Sebrell
评论会员:游客 时间:2011/12/14
!喜有一种方法如何确定位图的大小。尝试了这一点:CheckBoxState状态=box.CheckState?CheckBoxState.CheckedNormal:CheckBoxState.UncheckedNormal;尺寸bitmapSize=CheckBoxRenderer.GetGlyphSize(e.Graphics,州);CheckBoxRenderer.DrawCheckBox(e.Graphics,新的点(e.Bounds.X,e.Bounds.Y),新的Rectangle(新站(e.Bounds.XbitmapSize.Width,e.Bounds.Y),新的大小(e.Bounds.Width,e.Bounds.Height))box.Text,this.Font,TextFormatFlags.Left,(e.StateDrawItemState.Focus)==0,状态);
赛义德Moshiur Murshed
评论会员:游客 时间:2011/12/14
首先,我谨向你的好主意。我想使一对夫妇建议以及。您可能会考虑的OnDrawItem(DrawItemEventArgsE)方法,而不是重写DrawItem事件写一个单独的事件处理方法。它通常会导致更快的性能。只要确保你包括base.OnDrawItem(E)的调用,以确保事件引发此外,ComboBox控件中包含的类型ComboBoxStyleDropDownStyle属性,其中包含三个值,其中ComboBoxStyle.DropDownList防止用户能够编辑列表项希望这有助于imgsrc=http://www.orcode.com/upimg/2011_12_14_13_22_55_3.gif
Ewino
评论会员:游客 时间:2011/12/14
我同意与扎贝尔。您可以轻松地重写OnDrawItem,而不是处理DrawItem事件。但说实话的想法是好的。其余的我可以设法改变自己。赛义德MoshiurMurshed
服务台
评论会员:游客 时间:2011/12/14
第一个建议是非常有帮助,感谢你,我会尝试,我自己。第二个虽然没有工作,以及(或它只是恨我吗?{五})通过设置控件ComboBoxStyle.DropDownList模式和点击复选框,封闭的ComboBox显示CheckBox的整体(文本和小广场的V带或不带)。任何想法?
Ewino
评论会员:游客 时间:2011/12/14
我遇到了同样的问题-我的最终代码(写在VB.net和其他一些调整)如下-希望这将有助于给别人:{BR}公共类CheckComboBox继承System.Windows.Forms.ComboBox的PublicSubNew()NBSP-;Me.DrawMode=System.Windows.Forms.DrawMode.OwnerDrawFixedMe.DropDownStyle=系统。Windows.Forms.ComboBoxStyle.DropDownList的AddHandlerMe.DrawItem,AddressOfDrawItemHandlerNBSP;-;的AddHandlerMe.SelectedIndexChanged,AddressOfSelectedIndexChangedHandlerENDSUB新System.Drawing.PointDIMDefaultPoint(系统Int32.MinValue,System.Int32.MinValue)分DrawItemHandler(BYVAL发件人为System.Object,BYVALe由于System.Windows.Forms.DrawItemEventArgs){BR}DIMDrawIndex作为System.Int32的e.Index如果DefaultPoint.XLT,GTSystem.Int32.MinValueDefaultPoint.YLT,GT;System.Int32.MinValue然后-;如果e.Bounds.X=DefaultPoint.Xe.Bounds.Y=DefaultPoint.Y然后-;DrawIndex=-1如果NBSP结束;-;如果NBSP结束;e.DrawBackground()如果DrawIndexLT;0或不Me.DroppedDownNBSP-;如果DefaultPoint.X=System.Int32.MinValueDefaultPoint.Y=System.Int32.MinValue然后NBSP-;DefaultPoint=e.Bounds.Location结束如果{BR}e.Graphics.DrawString(Me.SelectedText,Me.Font,新System.Drawing.SolidBrush(e.ForeColor),e.Bounds)返回NBSP结束如果NBSP如果不TypeOf运算Me.Items(DrawIndex)CheckComboBoxItem然后-;e.Graphics.DrawString(Me.Items(DrawIndex)的ToString,Me.Font,新System.Drawing.SolidBrush(e.ForeColor),E边界)返回end如果NBSP昏暗的项目作为CheckComboBoxItem=CTYPE(Me.Items(DrawIndex),CheckComboBoxItem)NBSP-;System.Windows.Forms.Vi​​sualStyles.CheckBoxState=System.Windows.Forms.Vi​​sualStyles.CheckBoxState.CheckedNormalNBSP昏暗的CheckState;-;如果没有Item.Checked然后-;的CheckState=System.Windows.Forms.Vi​​sualStyles.CheckBoxState.UncheckedNormal如果NBSP结束;System.Windows.Forms的。CheckBoxRenderer.RenderMatchingApplicationState=TRUESystem.Windows.Forms.CheckBoxRenderer.DrawCheckBox(e.Graphics,新System.Drawing.Point(e.Bounds.X,e.Bounds.Y)的CheckState)System.Drawing.Size=System.Windows.Forms的昏暗的大小。CheckBoxRenderer.GetGlyphSize(e.Graphics的CheckState)System.Drawing.Rectangle=e.BoundsNBSPDIMTextBounds-;TextBounds.X=Size.WidthTextBounds.Width-=Size.Width{BR}e.Graphics.DrawString(Me.Items的ToString(DrawIndex),Me.Font,新System.Drawing.SolidBrush(e.ForeColor),TextBounds)ENDSUB公共事件CheckStateChanged为System.EventHandlerNBSP私人小组SelectedIndexChangedHandler(BYVAL作为System.Object的,BYVALe由于发件人)如果TypeOf运算Me.SelectedItemCheckComboBoxItem{BR}昏暗的项目作为CheckComboBoxItem=CTYPE(Me.SelectedItem,CheckComboBoxItem)NBSP;-;Item.Checked=不Item.CheckedNBSPMe.SelectedItem=没有的RaiseEventCheckStateChanged(项目,E){BR}Me.DroppedDown=TRUENBSP-;结束如果ENDSUB公开重载ReadOnly属性SelectedText()System.String-;DIM作为System.String选择="为每个项目为System.ObjectMe.Items-;-;如果TypeOf运算项目CheckComboBoxItem然后NBSP-;如果CTYPE(项目,CheckComboBoxItem)托运-;如果选中LT,GT","-;选择放大器;=";"-;结束如果NBSP;-;选择放大器;=CType运算(项目,CheckComboBoxItem)-;结束如果NBSP;-;结束如果下一步-;返回选择完高端物业NBSP公共ReadOnly属性SelectedItems()作为System.Collections.Generic.List(CheckComboBoxItem)NBSP;DIM作为新System.Collections.Generic.List选择(CheckComboBoxItem)NBSP;-;为每个项目作为System.Object的Me.Items-;NBSP-;如果TypeOf运算项目CheckComboBoxItem然后-;如果CTYPE(项目,CheckComboBoxItem),然后选中。NBSP;-;Selected.Add(CTYPE(项目,CheckComboBoxItem))NBSP-;如果NBSP结束;-;如果NBSP结束;下一页返回选择最终获取高端物业结束类
carlos_hgo
评论会员:游客 时间:2011/12/14
我有没有尝试过,但它看起来像它的要去工作感谢分享!imgsrc=http://www.orcode.com/upimg/2011_12_14_13_22_55_9.gif
pennidren
评论会员:游客 时间:2011/12/14
?我缺少的东西CheckComboBoxItem它发送消息"CheckComboBoxItem是没有定义"什么想法?感谢