锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C#开源技术 / Winform复选下拉ComboBox控件

服务方向

人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发

联系方式

固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品原创,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究。点名“简易百科”和闲暇巴盗用锐英源原创内容。

Winform复选下拉ComboBox控件


本文要点在于组合窗口形成一个复杂控件,这方向非常有意思。

最近用WPF,研究了里面有CheckComboBox,这种结合性质的控件是初学者进阶中级程序员的好实践项目,就是初学者实现不了,研究掌握结合点的机制,水平也会增加不少。本文虽然是Winform方向,但是都是ComboBox,有兴趣翻译学习,翻译自codeproject,codeproject看不懂,找锐英源。

 

介绍

此控件源于我创建CheckedListBox控件的需要,该控件在所选项可见时不会占用窗体上的太多空间。虽然已经有一些使用所有者绘制控件的示例(例如,绘制ComboBox的ListBox部分),但由于一些缺点,我并不完全满意,因此我提出了一个新版本,即CheckedComboBox,它具有以下功能:

 

只读文本部分,显示选中的项目。

每个选中的项目在文本部分显示为一个字符串,每个字符串由我可以定义的自定义分隔符分隔。

列表部分保持打开,直到用户完成选择。

选中/取消选中所有项目。

通过键盘显示/隐藏列表部分。

尽可能模拟.NET ComboBox。

从VisualStudio调色板中使用它(作为自定义控件)。

实施

CheckedComboBox派生自ComboBox。为了避免在用户完成选择之前列表部分消失的问题,我决定捕捉DropDown事件并显示我自己的列表部分,该列表部分由一个表单组成,该表单的客户端区域完全由一个CheckListBox填充。Form和CheckListBox都是我自己的自定义版本,因为我需要重写一些默认行为。

 

因此,我的自定义列表部分会出现在DropDown事件中,或者当用户在CheckedComboBox具有焦点时按下向下箭头时。我将OnDropDown()、OnKeyDown(()和OnKeyPress()方法重写为:

显示下拉列表,以及

防止任何键盘输入,以便使文本部分为只读。

protected override void OnDropDown(EventArgs e) {
    base.OnDropDown(e);
    DoDropDown();    
}

private void DoDropDown() {
    if (!dropdown.Visible) {
        Rectangle rect = RectangleToScreen(this.ClientRectangle);
        dropdown.Location = new Point(rect.X, rect.Y + this.Size.Height);
        int count = dropdown.List.Items.Count;
        if (count > this.MaxDropDownItems) {
            count = this.MaxDropDownItems;
        } else if (count == 0) {
            count = 1;
        }
        dropdown.Size = new Size(this.Size.Width, 
                       (dropdown.List.ItemHeight + 1) * count);
        dropdown.Show(this);
    }
}

protected override void OnKeyDown(KeyEventArgs e) {
    if (e.KeyCode == Keys.Down) {        
        OnDropDown(null);
    }
    // Make sure that certain keys or combinations are not blocked.
    e.Handled = !e.Alt && !(e.KeyCode == Keys.Tab) &&
        !((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.Right) || 
    (e.KeyCode == Keys.Home) || (e.KeyCode == Keys.End));
    base.OnKeyDown(e);
}

protected override void OnKeyPress(KeyPressEventArgs e) {
    e.Handled = true;
    base.OnKeyPress(e);
}

注:OnKeyPress不处理就没输入。

 

现在,作为表单的列表部分将保持打开而不关闭(实际上是隐藏的),直到用户按Esc键(Escape按钮)取消任何更改,按Enter键接受所有更改,或用鼠标单击列表之外的任何位置,这是组合框的通常行为。

 

为了实现这一点,我必须捕捉窗体的Deactivate事件(对于鼠标点击行为)和键盘事件(对于Esc、Enter行为)。此外,如果用户在列表部分具有焦点时按下Del(删除按钮)或Shift+Del,则将分别取消选中/选中所有项目,这将提供一个有用的(对我来说:-)键盘快捷键。请注意如何使用自定义CCBoxEventArgs类来区分Deactivate消息是来自框架(即鼠标点击)还是来自键盘(因为我捕获击键,所以我可以控制键盘)。

protected override void OnDeactivate(EventArgs e) {
    base.OnDeactivate(e);
    CCBoxEventArgs ce = e as CCBoxEventArgs;
    if (ce != null) {
        CloseDropdown(ce.AssignValues);
    } else {

        CloseDropdown(true);
    }
}

使用代码

代码作为一个演示项目提供,您可以运行它并将其作为使用示例。为了在代码中使用CheckedComboBox,您只需要一个文件CheckedComboBox.cs。虽然我还没有将它变成一个功能齐全的Visual Studio控件,它包含了所有的箭头和滚动,但一旦编译了项目,CheckedComboBox应该会出现在Visual Studio工具箱调色板中的组件下,您可以将其拖放到设计器中的窗体上。

 

或者,您可以通过手动编写如下所示的代码来声明和创建CheckedComboBox的实例,从而非常容易地使用它:

private CheckedComboBox ccb = new CheckedComboBox();

// If more than 5 items, add a scroll bar to the dropdown.
ccb.MaxDropDownItems = 5;
// Make the "Name" property the one to display, rather than the ToString() 
// representation of the item.
ccb.DisplayMember = "Name";
// Set a separator for how the checked items will appear in the Text portion.
ccb.ValueSeparator = ", ";

添加数据:

private string[] coloursArr = { "Red", "Green", "Black", 
                                "White", "Orange", "Yellow", 
                                "Blue", "Maroon", "Pink", "Purple" };

for (int i = 0; i < coloursArr.Length; i++) {
    CCBoxItem item = new CCBoxItem(coloursArr[i], i);
    ccb.Items.Add(item);
}

CCBoxItem类如下:

public class CCBoxItem {
    private int val;
    public int Value {
        get { return val; }
        set { val = value; }
    }
    private string name;
    public string Name {
        get { return name; }
        set { name = value; }
    }
    public CCBoxItem() {
    }
    public CCBoxItem(string name, int val) {
        this.name = name;
        this.val = val;
    }
    public override string ToString() {
        return string.Format("name: '{0}', value: {1}", name, val);
    }
}

您还可以通过编程方式检查项目或将其CheckState设置为Checked、Unchecked或Indeterment。请注意,用户无法从用户界面将项状态设置为“不确定”,只能通过编程方式设置(除非您希望处理ItemCheck通知并在其中添加自己的逻辑)。

// Check first item (index == 0)
ccb.SetItemChecked(0, true);
// Set the CheckState of the 2nd item in the list to Indeterminate.
ccb.SetItemCheckState(1, CheckState.Indeterminate);

您可能会在应用程序中捕捉到的最有趣的事件是当下拉部分关闭时(DropDownClosed)和当项选中状态即将更改时(ItemCheck)。您可以注册事件处理程序并照常处理事件。

 

请注意,DropDownClosed事件可直接从ComboBox获得,但ItemCheck必须从CheckListBox获得。

在上面的代码中,可以通过CheckedItems属性看到选中的项。类似地,CheckedIndices将返回一个已检查索引的集合。这两个集合都对应于.NET CheckedListBox集合,因此这里没有什么不熟悉的。

this.ccb.DropDownClosed += new System.EventHandler(this.ccb_DropDownClosed);
ccb.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ccb_ItemCheck);

// Handler implementation

private void ccb_DropDownClosed(object sender, EventArgs e) {
    txtOut.AppendText("DropdownClosed\r\n");
    txtOut.AppendText(string.Format("value changed: {0}\r\n", ccb.ValueChanged));
    txtOut.AppendText(string.Format("value: {0}\r\n", ccb.Text));
    // Display all checked items.
    StringBuilder sb = new StringBuilder("Items checked: ");
    // Checked items can be found via the CheckedItems property.
    foreach (CCBoxItem item in ccb.CheckedItems) {
        sb.Append(item.Name).Append(ccb.ValueSeparator);
    }
    sb.Remove(sb.Length-ccb.ValueSeparator.Length, ccb.ValueSeparator.Length);
    txtOut.AppendText(sb.ToString());
    txtOut.AppendText("\r\n");
}

private void ccb_ItemCheck(object sender, ItemCheckEventArgs e) {
    CCBoxItem item = ccb.Items[e.Index] as CCBoxItem;
    txtOut.AppendText(string.Format("Item '{0}' is about to be {1}\r\n", 
                                     item.Name, e.NewValue.ToString()));
}
友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内