返回首页

{A}
{S0}
版本1.3 - 检索与固定宽度/隐藏列。支持从右至左语言。简介
的用户,我写有填写表格,包括许多代码从组合框选择的方案。这些代码是固定的。普通用户不能进入新的代码,但必须选择一个预定的值列表。做数据录入的人都非常熟悉的代码和键盘中心。他们不想使用鼠标每次输入一个值。查看数据,但不这样做大量的数据录入"的人不熟悉的代码,但要看到更详细的文字描述每个代码是与。
的解决方案,我试图创建一个多组合框,链接到一个只读的TextBox。当用户从ComboBox中选择一个项目,它会同时显示的代码在一个多下拉列表和描述。但是,当ComboBox的封闭,我想显示在文本框链接到它的ComboBox中的代码和描述。在ComboBox的代码将绑定到数据库,并在TextBox将未绑定的,仅供参考之用。通过这种方式,用户都将能够看到的信息是最重要的是他们。
我也想强制用户只能选择在ComboBox列表的项目。用户无法输入任何文字,是不是有效。因此,这种控制可以工作在两种模式之一:自动完成=真。当"自动完成"设置为true,控制的行为像一个ComboBoxStyle.DropDown。用户可以键入一个值,它会自动完成对基于关联的值列表。如果用户键入一个字母,将导致一个无效的代码输入,击键抑制。自动完成=假。当"自动完成"设置为false,控制的行为就像一个ComboBoxStyle.DropDownList(即使它实际上有一个ComboBoxStyle.DropDown的视觉风格)。在这种模式下,用户可以打一个字母或数字控制,将通过该列表中的值,字母或数字开头的所有周期。但封闭组合框不会显示像一个ListBox中的列之间的分界线。它只是显示的代码值,无论ComboBox是多么广泛。背景
这篇文章和我创建的控制不会有可能如果没有工作,他写道:控制。这是他的工作,帮助我克服一切艰难的障碍,阻止我创造我所需要的。有一次,我发现他的代码,我是能够创造出一个解决方案,在大约一天。如果您喜欢这个控制,并发现它有用,首先感谢他(和最)。而不是重复他所有的文档在这里,我建议你读他的网页上的控制,如果你想更好地了解了我的控制是如何工作的。
我想也想感谢,因为我用我的自动完成功能的基础上他的论坛的建议。使用代码
若要使用此代码,所有你所要做的的是从工具箱选择​​一个TextBox一起MultiColumnComboBox和形式。
然后,您可以设置以下属性:"自动完成"功能:真正使得它像一个下拉自动完成。假使得它像一个只读DropDownList的行为。AutoDropdown:当你按一个键,它会自动下拉列表,所以你可以看到选择。在"自动完成"=真正的模式,它会自动关闭,当你输入一个有效的选择。BackColorEven:列表中甚至项目的背景色。默认是白色的。BackColorOdd:背部颜色列表中的多项。默认是白色的。我总是用一个黑色的前景色,所以我没有码的奇数/偶数ForeColor属性。LinkedColumnIndex:什么是您想要显示的TextBox列的索引?我的大部分形式ComboBox中显示0列和TextBox中显示列1。LinkedTextBox:从窗体上的控件的下拉列表中选择一个文本框。当一个TextBox到ComboBox,它会自动设置为ReadOnly = true和在设计时的TabStop =假。
击中Escape键清除ComboBox和其相关联的TextBox。版本1.1的变化
,一旦我开始使用的控制,并成为多了几分熟悉编写代码Nishant,我意识到有一个,我想才能有它的行为方式,我需要它来的一些变化。所以,我调整了一点:Delete键清除Esc键以同样的方式在原来的版本中没有的控制和链接的文本框。Backspace键的行为像一个左箭头键。它不会从代码中删除的信件,因为我想执行唯一有效的选择。它只是将插入符返回一个空间和位置的清单。原来的版本要在下拉列表中的每一个项目,遍历和动态设置列的宽度。由于另一名成员在反馈中指出,这是一个问题时,与许多公共属性的对象,因为它们都显示在列表中。我决定把用户指定的项目,以便列可以通过值设置为0隐藏的列宽。我添加了一个例子,演示,展示了一种以编程方式引用一个隐藏的列选定ComboBox项,如果有人想隐藏一列,但使用类似ID或键值。
添加这些功能增加了两个属性:ColumnWidthDefault:如果列的宽度是没有明确宣布,这将是该列的宽度。列宽:一个分隔的字符串列的宽度。要实现此功能,我复制一个Microsoft Access中使用分号分隔的字符串指定的列宽的成语。一个空白列设置为默认。
这里有几个例子:

ColumnWidthDefault = 75

ColumnWidths =

结果:每列将显示默认宽度为75。
绑定到六列的对象:{C}
结果:Column0 = 100,此行中column1 = 75(默认),Column2的= 200;其余三个所有列默认为75。
绑定到一个对象有三列:
ColumnWidthDefault = 75

ColumnWidths = 0;50;150

结果:Column0与宽度为零,将Column1 = 50,Column2的= 150隐藏。
绑定到六列的对象:
ColumnWidthDefault = 0

ColumnWidths = 50;100

结果:Column0 = 50,此行中column1 = 100,其余全部是隐藏的,因为他们是默认值为零。版本1.2的变化
将控件绑定到一个数组的对象,有大量的属性造成的问题。虽然数据集的定义它们的顺序,与很多公共属性的对象将显示在其列将显示在下拉列表中以随机顺序的属性。这使得它无法使用列索引来设置列的宽度,因为没有保证,一列将始终被捆绑到一个特定的指数。
为了解决这个问题,我添加了一个新的属性,使程序员可以定义列将显示名称和它们将出现。的ColumnName:列名的分隔的字符串。名的顺序决定了列的顺序。一个空字符串显示所有的列。看起来像这样一个例子:
ProductCode;ProductCategory;ProductDescription

几个在我的程序的下拉列表中有很多的代码(数百个)。在大部分时间内,用户可以选择一些很常见的选择,很容易记住。但是,当一个新的用户学习系统,或有经验的用户需要找到一个很少使用的项目,一些搜索工具可以有所帮助。
由于这个原因,我添加了一个OpenSearchForm事件类。当用户点击LT; F3gt;键(标准的Windows搜索键),这个事件被解雇。程序员可以创建任何他喜欢的那种搜索表单,并把此事件​​。我增加了一个搜索表单示例演示,用户可以在其中输入一个搜索词,按下回车键,将在位于搜索网格和字符串。双点击网格中的一个项目,设置在ComboBox中的价值和关闭窗体。为了测试这一点,用户应该去一个ComboBox列出了所有的国家,打LT; F3gt;,键入字quot; Northquot;,并打回车键几次看到它通过国家循环它找到。
要打开搜索表单在我的演示程序,我添加了一个单一的程序:
private void multiColumnComboBox_OpenSearchForm(object sender, EventArgs e)

{

    FormSearch newForm = new FormSearch((MultiColumnComboBox)sender);

    newForm.ShowDialog();      

}

然后,我这单一事件的形式,每个ComboBox OpenSearchForm事件链接。搜索表单,然后是打开设置DataSource的搜索表单的DataGridView的DataSource通过组合框。我用的是ColumnNameCollection和传递ComboBox来确定哪些列显示在网格ColumnWidthCollection。

此搜索日常工作为我所有的例子,但之一。如果一个ComboBox的数据源是一个数组对象暴露了很多物业,下拉列表看起来很好的,如果我使用的语句columnNames属性只显示我想看到的属性:
{S2}
但是,如果我打LT; F3gt;键打开搜索列表,该列表将失去其订购:
{S3}
,而不是显示Property0,Property1,Property2,它会显示在底层数组的随机顺序列。甚至当我硬编码的位置,它仍然会忽略这些设置在这一个实例。搜索和双击工作得很好,只是列的顺序,我想他们不会。小对象和数据集,像他们应该工作。
我是唯一的办法能够解决这个的,有大类实现只暴露接口的属性,应该会出现在ComboBox:
//An interface that only shows properties 0, 1 & 2

public interface ICombo012

{

    string Property0

    {

        get;

    }



    string Property1

    {

        get;

    }



    string Property2

    {

        get;

    }

}



// A class that has 10 properties but can display

// properties 0, 1 & 2 or properties 1 & 9 

// through two different interfaces

public class ComplexObject : ICombo012, ICombo19

{

    //Class with 10 properties defined here

}

将ComboBox绑定到更小的接口,允许我使用较大的物体,没有问题的。我不知道这是否是最好的方式来解决这个问题,但因为这是一个学习的过程对我来说,我相信会有人指出,一个更优雅的解决方案,如果有一个可用。即使它的希望,我将最终能够提炼成一个有用和可靠的控制,将一些问题,我的目标是后每一套改善。版本1.3的变化
我添加为从右至左语言的支持。如果语言是LeftToRight,我在OnDrawItem事件中绘制字符串,零列开始和结束的最后一列,使用默认设置。如果是从右至左的语言,我提请以相反的顺序列,从最高的指数下降到零。我还可以使用StringFormat对象在从右至左的风格保持一致的字符串。
此更新还暴露了一个小quot; flawquot;在早期版本。当设置在OnDropDown事件的DropDownWidth,我没有计算垂直滚动条的宽度,如果它是目前。在LeftToRight的语言,这将截断尾随的最后一列中的字符,并可以quot; fixedquot;通过更广泛的最后一列。
,但从右至左语言,垂直滚动条的存在将晦涩的第一列(最右边)的显著特征。只有这样,才能解决这个问题,以确保垂直滚动条的宽度也增加了,每当Items.Count是比MaxDropDownItems。版本1.3.1变化
,我收到了在荷兰从ONNO Sloof电子邮件表明,添加以下行:
protected override void OnSelectedValueChanged(EventArgs e)

{    

    base.OnSelectedValueChanged(e);



    .



    .



    .



}

的OnSelectedValueChanged事件,将有助于与绑定。按照他的建议,我此行到1.3.1版本。历史1月31日,2008 - 1.3.1版本出版。2007年12月26日 - 版本1.3发布。2007年8月24日 - 版本1.2发布。2007年8月22日 - 版本1.1发布。2007年8月14日 - 文章首次发表。

回答

评论会员:_Jordan_JRD_ 时间:2011/12/14
谢谢你的控制。这是非常不错。我想念这里的一件事是自动计算可见列的宽度。我会建议延长ColumnWidths属性的语法,并允许有把'自动'的关键字,而不是一个固定的宽度。
,使我们可以这样定义的列的宽度:"10;汽车40;汽车"
关于

约旦
评论会员:会员7409541 时间:2011/12/14
只是在玩。围绕这个代码得到的东西的感觉。我注意到了一个错误,似乎只发生与Windows 7 Aero中,列表项相互重叠的,当你滚动通过大量的项目清单。

还有另一个家伙似乎有同样的问题:


有什么想法?

感谢分享这个 - !很好的例子BR}修订于12月10日,2010 10:33 PM
评论会员:华张玉军 时间:2011/12/14
有用
评论会员:CICCIOLO69 时间:2011/12/14
您好,
有人加入这个真棒控制到一个DataGrid?

预先感谢
评论会员:petedotg 时间:2011/12/14
很想知道这其中的答案,以及

的问候,

皮特
评论会员:。Capilano 时间:2011/12/14
喜。强大的控制。感谢发展。
我在我的整个应用程序中使用很多组合框。我最近下载的代码从代码项目。
反正有告诉我有哪个版本的控制?
再次感谢您的工作。



修改,2009年11月5日,日(星期四)下午07:53
评论会员:langtudien 时间:2011/12/14
我有我MultiColumnComboBox 2列的DataTable:

ITEMID:INT:1,2,3,4,5,6,7,8,9,10,11,12,13,14
项目名称:串

cbxItem.DisplayMember ="ITEMID";
当我的用户输入"1"或"2"或... ..."9"在cbxItem仍然是确定的,它会自动选择他们所需要的项目

但是,当他们要选择按1 13 3

问题是惜售:第1项是selecled,然后选择第3项是,我的用户所需要的项目13

我该如何解决呢?
评论会员:会员2981 时间:2011/12/14
感谢你的代码共享,出色的工作
我想知道天气您有任何关于如何添加一个图像/图标每行吗?sugesstion
感谢
评论会员:欧阳Caillouet 时间:2011/12/14
对不起。我从来没有研究这是什么会采取或试图尝试。所以,我没有任何见解到一个很好的或容易解决。

如果我要添加此功能,我想看看其他用户如何做了它,并尝试融入我自己的代码
评论会员:josephchild 时间:2011/12/14
看来当我修改几个不同的特性,火灾关闭我的SelectedIndexChanged事件。这是正常的吗?
,是有方式,它不会触发该事件呢?
伊夫注意到,当我修改数据源和ValueMember专门
评论会员:。欧阳Caillouet 时间:2011/12/14
是可能的编程bind和unbind事件。如果你不想火的事件,当你改变一个DataSource或一个。ValueMember,你可以取消绑定更改前的事件,然后绑定事件之后。换句话说,开/关切换事件。


//Unbind the event (turn it off)

multiColumnComboBox5.SelectedIndexChanged -= new System.EventHandler(this.multiColumnComboBox5_SelectedIndexChanged);

 

//Do something to the control (i.e. Change its .DataSource & .DataMember)

multiColumnComboBox5.DataSource = dataTable5;

multiColumnComboBox5.DisplayMember = "Name";

multiColumnComboBox5.ValueMember = "ID";

multiColumnComboBox5.SelectedIndex = -1;

multiColumnComboBox5.Text = "";

textBox5A.Text = "";

 

//Bind the event back (turn it back on)

multiColumnComboBox5.SelectedIndexChanged += new System.EventHandler(this.multiColumnComboBox5_SelectedIndexChanged);

如果你看看在Form1.designer.cs文件演示的一部分,你会发现,上面的行是在窗体设计器设置属性自动创建。您可以简单地剪切和粘贴到你的代码这一行,改变"=""-="撤消设计师设置的约束力
评论会员:游客 时间:2011/12/14
|即使是在提供的范例。KHANBABA:数字键5和8不起作用。ñ提供的样本,左边如果你一拳从138键盘上的键不起作用,它只能显示135甚至138,是有列表中在第二个组合框。同样是与5例。伟大的工作修改,2009年5月10日,日(星期日)8:16
欧阳Caillouet
评论会员:游客 时间:2011/12/14
我无法重现这个问题。当我下载的例子,键入138,"138"出现在ComboBox中,然后自动关闭,并在链接文本框中出现的"桔子"。这是我希望看到这个特殊的组合配置方式的基础上的行为。我试了其他几个号码,他们似乎都正常工作。我测试的其他组合,每个乖巧,我希望他们为了说明各种可能的配置。它还这种方式工作,当我跑从VS2008的IDE以及。所以,我不知道为什么你看到不同的结果与您的副本。从我的结束,是难以解决的问题,如果我不能复制
。KHANBABA
评论会员:游客 时间:2011/12/14
我真的appriciate您的工作和我的意图,首先是不伤害你的感情我再次下载的演示和测试,它已与138的替代行为。一旦它显示135-"香蕉"上备用打开显示138-"桔子"。但是,如果我按135,它总是产生所需的结果,它始终是135-"香蕉"。同样的情况下,当你需要按345,它产生交替的结果,341和345,它的重复。还有一种情况是与127相同。如果您需要127产生交替的结果,127和123,一旦涉及123和第二轮就成了127。你只需要按住127127127127127,结果将是127123127123127。但如果你需要的是123,然后它好了所有的时间。我使用的输入语言和英语作为美国键盘美国,但我不这么认为,它可能是原因。如果只用我这个问题真的为我的{S4}的令人惊讶的
穆罕默德阿卜杜拉82
评论会员:游客 时间:2011/12/14
我上午用在一个雇员查找形成你的控制,并以这种形式我可以对现有的名称搜索如果存在它的确定您的控制做工精细,如果不是我希望能够写在ComboBox中,然后点击添加新的按钮添加非现有的名称我不知道这是可以做到!再伟大的工作
欧阳Caillouet
评论会员:游客 时间:2011/12/14
恭维。我很高兴你喜欢的控制。我来自一个ComboBox控制。然后,我覆盖KeyPress事件,所以新的控制行为完全相同的方式我想它。您可以修改这个例程的关键是取得控制时的行为方式的转变,。,例如,如果您移动最后一行的日常读取e.Handled=TRUE;例行顶部,然后取代行e.KeyChar=(char)0的;与e.Handled=FALSE;你容许不在列表中的项目被输入框。如删除,抑制Backspace键,如果你想允许该功能的代码,你将不得不做其他事情。您只需修改这一个程序,改变它的行为方式,当用户罢工的一个关键。另外要实现的是一个单一的KeyPress事件,我写了我的控制,适用于放置在窗体上的控件的所有副本的一部分。如果你想,你可以从我的控制中删除此例程,并为每个单独的控制形式的一部分作为个人KeyPress事件。有些人可能像我原来的控制。有人可以像正常的ComboBox。我希望这有助于
穆罕默德阿卜杜拉82
评论会员:游客 时间:2011/12/14
感谢{S4}非常有帮助的
leobaby
评论会员:游客 时间:2011/12/14
这里我试图...ValueMember我的数据源的CustomerID字段,的DisplayMember到CUSTOMERNAME。但CUSTOMERNAME是不是唯一的,因此需要一个多列组合框。但没有哪一个是选择的问题,与该名称的第一个被选中。我已经试过的解决方法,如设置的DisplayMember串联的查询值的名称编号,它似乎工作。但在该课程结束时,的DisplayMember需要CUSTOMERNAME。任何建议
?欧阳Caillouet
评论会员:游客 时间:2011/12/14
我是从您的文章,你说"CUSTOMERNAME独特的"和"这个名字的第一个被选中"意味着不确定1)你的意思是CUSTOMERNAME的值不是唯一的?例如,你有"李四"的名字多次在记录?2),或者你的意思是查询加载到ComboBox的值是加入"CUSTOMERNAME"和ComboBox的名称相同的两列总是显示该名称的第一列?如果它是第一个条件,我试着用我的演示程序,并与多个相同的物品ComboBox中显示正确的ID编号为每个选定的项目。因此,它似乎为我工作。如果是第二个条件,然后重复的列名的别名(使用"AS"关键字)所以它有一个独特的名称会解决这个问题:选择a.customerID,a.customerName,customerID2b.customerID, b.customerName的AScustomerName2从tableName1AINNERJOINtableName2Ba.relatedField=b.relatedField可以绑定CUSTOMERNAME,如果你想,如果你想绑定到第二个绑定到的第一个字段和customerName2因为我是您的具体问题的性质是不确定的,我希望这些问题的答案之一是有帮助的的。如果我完全误解的问题,那么这种非答案可以帮助你制定一个不同的描述您的问题,所以我可以帮你解决:欧阳Caillouet
I'been使用的控制,必然要一个DataTable 。
让我们假设我的
NBSP以下数据见下表;
的DataTable [水果]

fruitsid fruitsname fruitsdescription
1nbsp; NBSP - ; applenbsp; 红苹果
2nbsp; pineapplenbsp; 黄菠萝
3nbsp; etcnbsp; 等名称
NBSP。
然后,我必将与上表中的ComboBox中
的DisplayMember = fruitsname
ValueMembernbsp; fruitsid =
的SelectedValue = fruitsid

但是当我运行的应用程序,一些模糊的原因,当您尝试选择一个项目或
写项目要查找的文本,它只是选择第一和永远不会改变,或者如果你写的,或选择或做whathever ComboBox中仍然只是一个所选的项目。{BR }
这是一个错误或这是正常行为的控制的吗?
评论会员:马西莫Colurcio 时间:2011/12/14
的DisplayMember设置将直观地显示列

ValueMember设置将被绑定到数据库字段的列。

的SelectedValue设置或获取的ValueMember的电流值。

因此,举例来说,如果你有在你的程序下面的代码:

multiColumnComboBox1.DataSource    = dataTable1;

multiColumnComboBox1.Displaymember = fruitsname;

multiColumnComboBox1.ValueMember   = fruitsid;

multiColumnComboBox1.SelectedValue = 2;

将设置ComboBox的fruitsid = 2,将显示"菠萝"和存储"2"在数据库中保存记录时。

与原来的设置上述问题是,你拥有的SelectedValue = fruitsid。 fruitsid是的ColumnName或财产的描述。它不是一个变量,可以解除引用一个文本值,如1,2,3,

另一种方法是这样写的代码,可能会使其更加明确的:

dataTable1.Columns.Add("fruitsid ", typeof(String));

dataTable1.Columns.Add("fruitsname ", typeof(String));

dataTable1.Columns.Add("fruitsdescription", typeof(String));

 

multiColumnComboBox1.DataSource    = dataTable1;

multiColumnComboBox1.Displaymember = fruitsname;

multiColumnComboBox1.ValueMember   = fruitsid;

multiColumnComboBox1.SelectedValue = dataTable1[1]["fruitsid"];

你想的SelectedValue等于在相关数据集
在当前记录fruitsid领域所代表的价值
评论会员:欧阳Caillouet 时间:2011/12/14
反正有显示列的头(也许让可调整大小的列)?

PS:伟大的工作,你有我5
评论会员:josephchild 时间:2011/12/14
当我看到这个问题,我立即想到的是,列标题不应该是很难落实。但是,研究了一段时间之后,它看来,这是不是作为微不足道的,因为我首先想到的或谷歌搜索我一直在错误的地方。我会继续这方面的工作,看看我是否能找到一个解决方案。
在我写的方案,我总是知道将要在ComboBox中显示的值。因此,固定宽度的列做工精细适合我。
如果我创建一个商业计划,用户将加载到要显示的表值,然后我可能会想我列的大小动态表中的值的长度。
如果你看上面的文章,有一个项目的链接,我本来基础控制。该控件的作者,Nishant西瓦库玛,他的列自动调整大小,使用下面的代码:

        

protected override void OnMeasureItem(MeasureItemEventArgs e)

{

    base.OnMeasureItem(e);

 

    if (DesignMode)

        return;

 

    for (int colIndex = 0; colIndex < columnNames.Length; colIndex++)

    {

        string item = Convert.ToString(FilterItemOnProperty(Items[e.Index], columnNames[colIndex]));

        SizeF sizeF = e.Graphics.MeasureString(item, Font);

        columnWidths[colIndex] = Math.Max(columnWidths[colIndex], sizeF.Width);

    }

 

    float totWidth = CalculateTotalWidth();

 

    e.ItemWidth = (int)totWidth;

}
此代码的优点是,它集你为你的大小。缺点是,它消除了零的宽度隐藏的列,该矿已,因为它会动态每列大小。我敢肯定有办法,你可以结合这两种方法,如果你需要。以积极的宽度例如列是固定的,具有零宽度的列将被隐藏和列的宽度为-1将使用上面列出的方程动态调整大小的功能
评论会员:保罗吉尔 时间:2011/12/14
你发现一个解决显示列标题:
|