返回首页

&# 160; 下载演示项目 - 11 KB  60;
{S0}{S2} 简介
我不得不写在工作中多列组合框,支持通用的数据具有约束力,并且我想这可能证明为他人也有用。MultiColumnComboBox是一个ComboBox派生类的书面完全用C#和你可以把它绑定到任何数据源有多个列(虽然不要紧,如果它只有单个列)。它也适用在绑定模式,但它并没有太大的意义上使用它,如果你不使用数据绑定。类的用法
使用的类相当简单。一旦你有你的的数据源只需要设置DataSource属性MultiColumnComboBox类。控制不支持ComboBoxStyle.Simple风格,它除了将坚持DrawMode被设置到OwnerDrawVariable。例外的是抛出,这样你就不会无意中试图打破那些要么这是非常方便的局限性,因为Visual Studio的属性网格然后让你改变这些值。
{S3}
类已经在Windows XP SP2以及Windows Vista上测试(终极版)无论是从Visual Studio设计的角度,以及从运行时的角度。这里有一些例子填充控制各类型的数据源。在第一个例子,我们填充它的使用一个DataTable。

// Populate using a DataTable



DataTable dataTable = new DataTable("Employees");



dataTable.Columns.Add("Employee ID", typeof(String));

dataTable.Columns.Add("Name", typeof(String));

dataTable.Columns.Add("Designation", typeof(String));



dataTable.Rows.Add(new String[] { "D1", "Natalia", "Developer" });

dataTable.Rows.Add(new String[] { "D2", "Jonathan", "Developer" });

dataTable.Rows.Add(new String[] { "D3", "Jake", "Developer" });

dataTable.Rows.Add(new String[] { "D4", "Abraham", "Developer" });

dataTable.Rows.Add(new String[] { "T1", "Mary", "Team Lead" });

dataTable.Rows.Add(new String[] { "PM1", "Calvin", "Project Manager" });

dataTable.Rows.Add(new String[] { "T2", "Sarah", "Team Lead" });

dataTable.Rows.Add(new String[] { "D12", "Monica", "Developer" });

dataTable.Rows.Add(new String[] { "D13", "Donna", "Developer" });



multiColumnComboBox1.DataSource = dataTable;

multiColumnComboBox1.DisplayMember = "Employee ID";

multiColumnComboBox1.ValueMember = "Name";

DisplayMember属性将决定价值的有形在ComboBox的编辑框部分。而ValueMember属性将决定哪些列将显示在粗体。如果你看看截图,可以清楚地看到这个动作。在接下来的例子中,我们使用一个自定义类型的数组。{C}
注意我们是如何设置的DisplayMember和ValueMember同一列的领域 - 这是完全没做。顺便说一下,如果你不设置ValueMember将使用默认的第一列。您必须设置的DisplayMember虽然,否则,你会看到一些奇怪的字符串取决于特定类型的ToString是如何实现的。我决定不提供一个默认的,因为它最有可能在非理想的结果列显示。我使用了我的第三下拉列表样式组合框例如,并用一个Listlt; GT;对象 - 尽管现在必须很明显,任何人读这基本上可以使用任何标准的数据源。
// Drop-down list (non-editable)



List<Student> studentList = new List<Student>(studentArray);

使用下拉列表的主要区别是,你会看到甚至当ComboBox是不下降的多个列。需要注意的是那些要防止这种行为可以检查,如果DrawItemEventArgs.StateComboBoxEdit标志(OnDrawItem方法)并相应地改变行为。对于我们的目的,这种行为是相当好,我个人认为它是更直观的方式做到这一点。而最后,您可以使用它没有数据绑定,但我想不出任何理由你为什么要这么做。
// Trying to use as a regular combobox



multiColumnComboBox4.Items.Add("Cat");

multiColumnComboBox4.Items.Add("Tiger");

multiColumnComboBox4.Items.Add("Lion");

multiColumnComboBox4.Items.Add("Cheetah");

multiColumnComboBox4.SelectedIndex = 0;
实施细节
我做的第一件事之一是隐藏DrawMode和DropDownStyle属性,以防止用户无意中设置不受支持的值。
public new DrawMode DrawMode 

{ 

    get

    {

        return base.DrawMode;

    } 

    set

    {

        if (value != DrawMode.OwnerDrawVariable)

        {

            throw new NotSupportedException("Needs to be DrawMode.OwnerDrawVariable");

        }

        base.DrawMode = value;

    }

}



public new ComboBoxStyle DropDownStyle

{ 

    get

    {

        return base.DropDownStyle;

    } 

    set

    {

        if (value == ComboBoxStyle.Simple)

        {

            throw new NotSupportedException("ComboBoxStyle.Simple not supported");

        }

        base.DropDownStyle = value;

    } 

}

我推翻OnDataSourceChanged可以使列名初始化。
protected override void OnDataSourceChanged(EventArgs e)

{

    base.OnDataSourceChanged(e);



    InitializeColumns();

}



private void InitializeColumns()

{

    PropertyDescriptorCollection propertyDescriptorCollection = 

        DataManager.GetItemProperties();



    columnWidths = new float[propertyDescriptorCollection.Count];

    columnNames = new String[propertyDescriptorCollection.Count];



    for (int colIndex = 0; colIndex < propertyDescriptorCollection.Count; colIndex++)

    {

        String name = propertyDescriptorCollection[colIndex].Name;

        columnNames[colIndex] = name;

    }

}

我使用DataManager属性返回CurrencyManager对象,管理的约束为控制对象。最初我还设置了一个宽度阵列0(后来的所需的宽度将被计算)。我也覆盖OnValueMemberChanged的方法,这样我可以正确的设定值成员列在内部,我使用的绘图代码值列在粗体文本绘制。
protected override void OnValueMemberChanged(EventArgs e)

{

    base.OnValueMemberChanged(e);



    InitializeValueMemberColumn();

}



private void InitializeValueMemberColumn()

{

    int colIndex = 0;

    foreach (String columnName in columnNames)

    {

        if (String.Compare(columnName, ValueMember, true, 

            CultureInfo.CurrentUICulture) == 0)

        {

            valueMemberColumnIndex = colIndex;

            break;

        }

        colIndex++;

    }

}

OnMeasureItem将被调用一次ComboBox中的每一行,这就是我做我的宽度计算。
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;

}

有趣的把戏这里是使用FilterItemOnProperty得到文本与特定列。宽度的计算是小学和我使用CalculateTotalWidth的方法计算的总宽度仅对个人所有列宽。我还可以添加的宽度垂直滚动条(之一的情况下显示)。我们还必须记住要覆盖OnDropDown定下宽度适当下降(记得这从组合框本身的宽度是不同的)。
protected override void OnDropDown(EventArgs e)

{

    base.OnDropDown(e);

    this.DropDownWidth = (int)CalculateTotalWidth();

}

现在我们来的肉类的OnDrawItem覆盖。
protected override void OnDrawItem(DrawItemEventArgs e)

{

    base.OnDrawItem(e);



    if (DesignMode)

        return;



    e.DrawBackground();



    Rectangle boundsRect = e.Bounds;

    int lastRight = 0;



    using (Pen linePen = new Pen(SystemColors.GrayText))

    {

        using (SolidBrush brush = new SolidBrush(ForeColor))

        {

            if (columnNames.Length == 0)

            {

                e.Graphics.DrawString(Convert.ToString(Items[e.Index]), 

                    Font, brush, boundsRect);

            }

            else

            {

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

                {

                    string item = Convert.ToString(FilterItemOnProperty(

                        Items[e.Index], columnNames[colIndex]));



                    boundsRect.X = lastRight;

                    boundsRect.Width = (int)columnWidths[colIndex] + columnPadding;

                    lastRight = boundsRect.Right;



                    if (colIndex == valueMemberColumnIndex)

                    {

                        using (Font boldFont = new Font(Font, FontStyle.Bold))

                        {

                            e.Graphics.DrawString(item, boldFont, brush, boundsRect);

                        }

                    }

                    else

                    {

                        e.Graphics.DrawString(item, Font, brush, boundsRect);

                    }



                    if (colIndex < columnNames.Length - 1)

                    {

                        e.Graphics.DrawLine(linePen, boundsRect.Right, boundsRect.Top, 

                            boundsRect.Right, boundsRect.Bottom);

                    }

                }

            }

        }

    }



    e.DrawFocusRectangle();

}

,虽然它的类中最长的函数(也可能是超过了马克克利夫顿批准在一个方法中的行的最大数量限制),这是相当简单。对于每一行,它会遍历所有列,得到列的文本,并提请与垂直线的文本将作为列分隔符。致谢 拉玛克里希纳Vavilala - 真棒有关的一些建议 实施。历史 2007年7月27日 - 文章首次发表。   ;

回答

评论会员:TimmermanJ 时间:2011/12/14
保存我的一天
评论会员:aaroncampf 时间:2011/12/14
超级有效和容易
评论会员:!sgissinger 时间:2011/12/14
我做了一些增强功能,以显示我只需要列。
我与实体拥有一个ComboBox的成员,我不需要使用实体框架。
例如,一个客户实体都不会忽略,电话,传真,电子邮件等..
,但我只想要显示它的名字和ComboBox的forName有能力保持在ComboBox项实体。
这些修改是兼容的东西,我stringly建议你实现Microdev后夫妇。

下面是代码修改

 

// <ADD>

private List<String> showOnlyColumns = new List<String>();

 

[Description("Set the columns that will be displayed in the dropdown list. If not set, all column will be shown.")]

[Category("Data")]

[DefaultValue(null)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

[Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]

public List<String> ShowOnlyColumns

{

    get

    {

        return showOnlyColumns;

    }

    set

    {

        showOnlyColumns = value;

    }

}

// </ADD>



// <MODIFY>

private float CalculateTotalWidth()

{

    float totWidth = 0;

 

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

    {

        // Conditional width calculation

        if (showOnlyColumns.Count == 0 ||

            showOnlyColumns.Contains(columnNames[colIndex]))

        {

            totWidth += (columnWidths[colIndex] + columnPadding);

        }

    }

 

    return totWidth + SystemInformation.VerticalScrollBarWidth;

}

 

protected override void OnDrawItem(DrawItemEventArgs e)

{

    [...]

        // Conditional display

        if (colIndex != valueMemberColumnIndex &&

            (showOnlyColumns.Count == 0 ||

            showOnlyColumns.Contains(columnNames[colIndex])))

        {

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

 

            boundsRect.X = lastRight;

            boundsRect.Width = (int)columnWidths[colIndex] + columnPadding;

            lastRight = boundsRect.Right;

 

            //if (colIndex == valueMemberColumnIndex)

            if (colIndex == displayMemberColumnIndex)

            {

                using (Font boldFont = new Font(Font, FontStyle.Bold))

                {

                    e.Graphics.DrawString(item, boldFont, brush, boundsRect);

                }

            }

            else

            {

                e.Graphics.DrawString(item, Font, brush, boundsRect);

            }

 

            if (colIndex < columnNames.Length - 1)

            {

                e.Graphics.DrawLine(linePen, boundsRect.Right, boundsRect.Top, boundsRect.Right, boundsRect.Bottom);

            }

        }

    [...]

    e.DrawFocusRectangle();

}

// </MODIFY>



// <ADD>

protected override void OnCreateControl()

{

    this.SelectedItem = null;

 

    base.OnCreateControl();

}

// </ADD>


下面是如何在代码中使用

 

multiColumnComboBox1.DataSource = _entityContext.CUSTOMER;

multiColumnComboBox1.DisplayMember = "TI_NAME";

 

// In code

multiColumnComboBox1.ShowOnlyColumns.Add("TI_NAME");

multiColumnComboBox1.ShowOnlyColumns.Add("TI_FORNAME");

 

// Or use Visual Studio String Collection Editor


评论会员:aaroncampf 时间:2011/12/14
你能否发表的所有代码
我不知道如何添加升级{S4}的

谢谢
评论会员:sgissinger 时间:2011/12/14

    [ToolboxItem(true)]

    [ToolboxBitmap(typeof(ComboBox))]

    public class MultiColumnComboBox : ComboBox

    {

        private List<String> _showOnlyColumns = new List<String>();

 

        public MultiColumnComboBox()

        {

            DrawMode = DrawMode.OwnerDrawVariable;

        }

 

        public new DrawMode DrawMode

        {

            get { return base.DrawMode; }

            set

            {

                if (value != DrawMode.OwnerDrawVariable)

                {

                    throw new NotSupportedException("Needs to be DrawMode.OwnerDrawVariable");

                }

                base.DrawMode = value;

            }

        }

 

        public new ComboBoxStyle DropDownStyle

        {

            get { return base.DropDownStyle; }

            set

            {

                if (value == ComboBoxStyle.Simple)

                {

                    throw new NotSupportedException("ComboBoxStyle.Simple not supported");

                }

                base.DropDownStyle = value;

            }

        }

 

        [Description("Set the columns that will be displayed in dropdown list. If not set, every columns will be shown.")]

        [Category("Data")]

        [DefaultValue(null)]

        [Browsable(true)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

        [Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]

        public List<String> ShowOnlyColumns

        {

            get { return _showOnlyColumns; }

            set { _showOnlyColumns = value; }

        }

 

        protected override void OnDataSourceChanged(EventArgs e)

        {

            base.OnDataSourceChanged(e);

 

            InitializeColumns();

        }

 

        protected override void OnValueMemberChanged(EventArgs e)

        {

            base.OnValueMemberChanged(e);

 

            InitializeValueMemberColumn();

        }

 

        protected override void OnDisplayMemberChanged(EventArgs e)

        {

            base.OnDisplayMemberChanged(e);

 

            InitializeDisplayMemberColumn();

        }

 

        protected override void OnDropDown(EventArgs e)

        {

            base.OnDropDown(e);

 

            this.DropDownWidth = (int)CalculateTotalWidth();

        }

 

        const int columnPadding = 5;

        private float[] columnWidths = new float[0];

        private String[] columnNames = new String[0];

        private int valueMemberColumnIndex = 0;

        private int displayMemberColumnIndex = 0;

 

        private void InitializeColumns()

        {

            PropertyDescriptorCollection propertyDescriptorCollection = DataManager.GetItemProperties();

 

            columnWidths = new float[propertyDescriptorCollection.Count];

            columnNames = new String[propertyDescriptorCollection.Count];

 

            for (int colIndex = 0; colIndex < propertyDescriptorCollection.Count; colIndex++)

            {

                String name = propertyDescriptorCollection[colIndex].Name;

                columnNames[colIndex] = name;

            }

        }

 

        private void InitializeValueMemberColumn()

        {

            int colIndex = 0;

            foreach (String columnName in columnNames)

            {

                if (String.Compare(columnName, ValueMember, true, CultureInfo.CurrentUICulture) == 0)

                {

                    valueMemberColumnIndex = colIndex;

                    columnWidths[colIndex] = 0;

                    break;

                }

                colIndex++;

            }

        }

 

        private void InitializeDisplayMemberColumn()

        {

            int colIndex = 0;

            foreach (String columnName in columnNames)

            {

                if (String.Compare(columnName, DisplayMember, true, CultureInfo.CurrentUICulture) == 0)

                {

                    displayMemberColumnIndex = colIndex;

                    break;

                }

                colIndex++;

            }

        }

 

        private float CalculateTotalWidth()

        {

            float totWidth = 0;

 

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

            {

                if (_showOnlyColumns.Count == 0 ||

                    _showOnlyColumns.Contains(columnNames[colIndex]))

                {

                    totWidth += (columnWidths[colIndex] + columnPadding);

                }

            }

 

            return totWidth + SystemInformation.VerticalScrollBarWidth;

        }

 

        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;

        }

 

        protected override void OnDrawItem(DrawItemEventArgs e)

        {

            base.OnDrawItem(e);

 

            if (DesignMode)

                return;

 

            e.DrawBackground();

 

            Rectangle boundsRect = e.Bounds;

            int lastRight = 0;

 

            using (Pen linePen = new Pen(SystemColors.GrayText))

            {

                using (SolidBrush brush = new SolidBrush(ForeColor))

                {

                    if (columnNames.Length == 0)

                    {

                        e.Graphics.DrawString(Convert.ToString(Items[e.Index]), Font, brush, boundsRect);

                    }

                    else

                    {

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

                        {

                            if (colIndex != valueMemberColumnIndex &&

                                (_showOnlyColumns.Count == 0 ||

                                _showOnlyColumns.Contains(columnNames[colIndex])))

                            {

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

 

                                boundsRect.X = lastRight;

                                boundsRect.Width = (int)columnWidths[colIndex] + columnPadding;

                                lastRight = boundsRect.Right;

 

                                if (colIndex == displayMemberColumnIndex)

                                {

                                    using (Font boldFont = new Font(Font, FontStyle.Bold))

                                    {

                                        e.Graphics.DrawString(item, boldFont, brush, boundsRect);

                                    }

                                }

                                else

                                {

                                    e.Graphics.DrawString(item, Font, brush, boundsRect);

                                }

 

                                if (colIndex < columnNames.Length - 1)

                                {

                                    e.Graphics.DrawLine(linePen, boundsRect.Right, boundsRect.Top, boundsRect.Right, boundsRect.Bottom);

                                }

                            }

                        }

                    }

                }

            }

 

            e.DrawFocusRectangle();

        }

 

        protected override void OnCreateControl()

        {

            this.SelectedItem = null;

 

            base.OnCreateControl();

        }

    }


评论会员:elizas 时间:2011/12/14
DataTable类的净支持一列从其他列的值的计算。

这意味着,可以说这是三列项目名称,价格,数量的dtItems我有一个DataTable,如果我需要添加另一列共此列计算值将价格*数量,这可以很容易做到无循环通过所有的行,它会自动计算运行期间"dtItems.Columns.Add("总计",typeof运算(INT),"价格*数量");"



任何建议赞赏。
欢呼声,
伊丽莎
评论会员:会员1370724 时间:2011/12/14
喜Nish,

感谢您的专业知识。我有一个问题...

我已经绑定到一个数据源如下:
var k4 = from p in ctx.vtblCustomerDivisions where p.vtblCustomers.active == true orderby p.vtblCustomers.name select new { p.vtblCustomers.name, p.cd, p.vtblCustomers.custId, p.division, p.address, p.city };

cboCustomerDivCd.DataSource = k4;

cboCustomerDivCd.DisplayMember = "custId";

cboCustomerDivCd.ValueMember = "cd";

cboCustomerDivCd.SelectedIndex = -1;

cboCustomerDivCd.Text = "";

cboCustomerDivCd.BackColorOdd = rowColor;

cboCustomerDivCd.ColumnWidths = "0;0;100;100;100;100";

当用户选择一个项目,我想设置标签的文本所选项目的第4列(师)在cobobox列表。
是否有一种方式来获得所选项目的第四列做?


丰富的B
评论会员:会员1974570 时间:2011/12/14


cs文件复制到我的项目后,我试图绑定到SQL数据源使用智能标记。当我试图运行它,我得到了与此
异常错误
PropertyDescriptorCollection propertyDescriptorCollection =
DataManager.GetItemProperties()

我错过什么?
任何意见?请!

TIA
评论会员:会员1974570 时间:2011/12/14

我收到一个NullReferenceException。

异常错误"的提法不设置到对象的实例"的PropertyDescriptorCollection声明

任何意见?

TIA的

修改,2009年4月1日,日(星期三)上午3:30
评论会员:Nishant西瓦库玛 时间:2011/12/14
代码的自动生成当你设置数据源,通过智能标记是什么?你可以粘贴在这里吗?

的问候,
Nish
评论会员:会员1974570 时间:2011/12/14
喜Nish

下面是代码的自动生成下"的InitializeComponent"
  ; / / multiColumnComboBox1
/ /
this.multiColumnComboBox1.DataBindings.Add(新System.Windows.Forms.Binding("的SelectedValue",this.ordersBindingSource,"身份证",TRUE))
this.multiColumnComboBox1.DataSource = this.ordersBindingSource
& #160; this.multiColumnComboBox1.DisplayMember ="OrderIDF";
this.multiColumnComboBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;

this.multiColumnComboBox1.FormattingEnabled = TRUE;  0; 新System.Drawing.Point this.multiColumnComboBox1.Location =(430,34);
this.multiColumnComboBox1.Name ="multiColumnComboBox1";
this.multiColumnComboBox1.Size =新(191,21)
 60;
this.multiColumnComboBox1.TabIndex = 43; & #160; this.multiColumnComboBox1.ValueMember ="身份证";

与接近尾声
私人MultiColumnComboBoxDemo.MultiColumnComboBox multiColumnComboBox1;

注:cs文件复制到项目
TIA
评论会员:会员1974570 时间:2011/12/14
喜Nish
我这一种修复。似乎有一个BindingSource的问题,所以我设置DataSource手动在DS中的DataTable。似乎工作。

TKS
:会员1974570
评论会员:游客 时间:2011/12/14
喜我的*.cs文件添加到我的项目?或我如何添加到工具箱?(我尝试使用选择项,右键单击工具箱面积,但随后说,这不是一个。NET组件!)任何意见?请
!Nishant西瓦库玛
评论会员:游客 时间:2011/12/14
这不是工具箱准备,所以你要cs文件添加到您的项目,然后手动改变一个ComboBox这个类的类型。的问候,Nishimgsrc=src="/KB/combobox/DotNetMultiColumnComboBox/Capture2.JPG"
会员1974570
评论会员:游客 时间:2011/12/14
!千恩万谢,Nish这就是我曾尝试。只是在想,也许有另一种方式
!软键
评论会员:游客 时间:2011/12/14
!喜如何我这个类添加到工具箱
?Nishant西瓦库玛
评论会员:游客 时间:2011/12/14
工具箱准备。您必须手动cs文件添加到您的项目。的问候,Nishimgsrc=src="/KB/combobox/DotNetMultiColumnComboBox/Capture2.JPG"
阿西夫拉赫曼
评论会员:游客 时间:2011/12/14
是。你可以用这些步骤。1。右键单击解决方案文件-添加新的项目-添加类库。命名(multiColumnBox)或任何东西。2。复制到新的类库项目的源文件。编译它。3。新的DLL文件中创建文件夹的bin/Debug或Bin/释放。4。现在右键单击工具箱在原来的项目。添加引用这个DLL。新的控制将显示在工具箱中以供将来使用。就是这样。关于阿西夫拉赫曼
。kevinlkingma
评论会员:游客 时间:2011/12/14
?任何方式来显示列标题
保罗吉尔
评论会员:游客 时间:2011/12/14
当我想通过单击滚动条或使用鼠标滚轮向下滚动的项目清单项目在错误的方向移动,这是解决
Microdev
评论会员:游客 时间:2011/12/14
?更改下面的标记:-(一)从显示列表中省略ValueMember(二),而不是突出的DisplayMemberValueMember/**报告错误修复或发送建议,*可以通过电子邮件nish@voidnish.com*/使用系统;使用System.Collections.Generic;使用System.Text;使用System.Windows.Forms;使用System.ComponentModel;使用System.Drawing;使用System.Globalization;命名空间MultiColumnComboBoxDemo{公共类MultiColumnComboBox:ComboBox中{ 公共MultiColumnComboBox(){DrawMode=DrawMode.OwnerDrawVariable;} 公共新DrawModeDrawMode {得到 { 返回base.DrawMode;}集合 { (价值!=DrawMode.OwnerDrawVariable) { 抛出新的回NotSupportedException("需要DrawMode.OwnerDrawVariable"); } base.DrawMode=值; }}公共新ComboBoxStyleDropDownStyle{得到{ 返回base.DropDownStyle;}集合{如果(值==ComboBoxStyle.Simple) { 抛出新的回NotSupportedException("ComboBoxStyle.Simple不支持"); }base.DropDownStyle=值;} }保护覆盖无效OnDataSourceChanged(级E) {base.OnDataSourceChanged(E);InitializeColumns()}保护覆盖无效OnValueMemberChanged(级E){base.OnValueMemberChanged(E) InitializeValueMemberColumn() }//****新-启动保护覆盖无效OnDisplayMemberChanged(级E){ base.OnDisplayMemberChanged(E) InitializeDisplayMemberColumn()}//****新-结束保护覆盖无效OnDropDown(级E){ base.OnDropDown(E) this.DropDownWidth=(INT)CalculateTotalWidth()}constint的columnPadding=5;私人浮法[]列宽=新浮法[0]私有String[]语句columnNames=新的String[0] valueMemberColumnIndex私人INT=0; //****新-启动displayMemberColumnIndex私人INT=0;//****新-结束私人无效InitializeColumns(){ PropertyDescriptorCollectionpropertyDescriptorCollection=DataManager.GetItemProperties() 列宽=新浮法[propertyDescriptorCollection.Count]语句columnNames=新的String[propertyDescriptorCollection.Count] 为(intcolIndex=0;colIndexLT;propertyDescriptorCollection.Count;colIndex) { 字符串名称=propertyDescriptorCollection[colIndex]名字;语句columnNames[colIndex]=名称; }} 私人无效InitializeValueMemberColumn() {INTcolIndex=0;的foreach(字符串的ColumnName在语句columnNames) {如果(的String.Compare(的ColumnName,ValueMember,真实,CultureInfo.CurrentUICulture)==0){ valueMemberColumnIndex=colIndex; //****新-启动 列宽[colIndex]=0; //****新-结束打破; } colIndex;} }//****新-启动私人无效InitializeDisplayMemberColumn(){ INTcolIndex=0; 的foreach(字符串的ColumnName在语句columnNames){ 如果(的String.Compare(的ColumnName的DisplayMember,真实,CultureInfo.CurrentUICulture)==0) { displayMemberColumnIndex=colIndex; 打破;}colIndex;}}//****新-结束私人浮动CalculateTotalWidth(){浮动totWidth=0;FOREACH(INT列宽的宽度){totWidth=(宽columnPadding);} 返回totWidthSystemInformation.VerticalScrollBarWidth;} 保护覆盖无效OnMeasureItem(MeasureItemEventArgsE){base.OnMeasureItem(E);(设计模式)返回为(intcolIndex=0;colIndexLT;columnNames.Length;colIndex) { 串项=Convert.ToString(FilterItemOnProperty(项[e.Index],语句columnNames[colIndex]));{BR} 的SizeF的SizeF=e.Graphics.MeasureString(项目,字体);列宽[colIndex]=Math.Max​​(列宽[colIndex,sizeF.Width);} 浮动totWidth=CalculateTotalWidth();e.ItemWidth=(INT)totWidth;}保护覆盖无效OnDrawItem(DrawItemEventArgsE){ base.OnDrawItem(E); (设计模式) 返回e.DrawBackground() 矩形boundsRect=e.Bounds; INTlastRight=0; (笔linePen=新朋(SystemColors.GrayText)){ (SolidBrush刷新SolidBrush(前景色)){ (columnNames.Length==0) { e.Graphics.DrawString(Convert.ToString([e.Index])项,字体,画笔,boundsRect); } ELSE { 为(intcolIndex=0;colIndexLT;columnNames.Length;colIndex) { //****新-启动(colIndex!=valueMemberColumnIndex) { //****新-结束 串项=Convert.ToString(FilterItemOnProperty(项[e.Index],语句columnNames[colIndex]));{BR} boundsRect.X=lastRight;boundsRect.Width=(int)的列宽[colIndex]columnPadding; lastRight=boundsRect.Right; //****新-启动 //如果(colIndex==valueMemberColumnIndex) (colIndex==displayMemberColumnIndex) //****新-结束 { (字体粗体字]=新的Font(字体,FontStyle.Bold)) { e.Graphics.DrawString(项目,粗体字],刷,boundsRect) } } ELSE{e.Graphics.DrawString(项目,字体,画笔,boundsRect); } (colIndexLT;columnNames.Length-1) { e.Graphics.DrawLine(linePen,boundsRect.Right,boundsRect.Top,boundsRect.Right,boundsRect.Bottom); }//****新-启动 }//****新-结束 } } } } e.DrawFocusRectangle()} }}
ksumm
评论会员:游客 时间:2011/12/14
您好,感谢伟大的文章,我用我自己扩展的多列组合框的基础上。我与现在的麻烦的事情是自动完成的,当我使用建议或SuggestAppend我想在辅助下拉列表中显示的列。我需要什么事件/消息陷阱,以吸引下拉显示的列我自己的任何想法。感谢基思
alias47
评论会员:游客 时间:2011/12/14
嗨,我使用一个SQL数据库的代码,使用下面的代码。然而,当ComboBox的下降,我只能看到12降下来列字符。你能看到我要去的地方错了?私人无效FillListControl(SQL字符串,MultiColumnComboBoxDemo.MultiColumnComboBoxCBO){ (SqlDataAdapter的DA=新SqlDataAdapter的(SQL,CON)){ 的DataTableDT=cbo.DataSource作为数据表;(DT==NULL){DT=新的DataTable(); da.Fill(DT);//填充表  cbo.DisplayMember=dt.Columns[1]的ColumnName; cbo.ValueMember=dt.Columns[0]的ColumnName;cbo.DataSource=DT; }ELSE da.Fill(dt)的;}}被传递的SQL是这样的......字符串STRSQL="选择0AssetType,为AssetTypeDescription" "UNIONSELECTAssetType.AssetType,AssetType.AssetTypeDescription" "AssetType";
alias47
评论会员:游客 时间:2011/12/14
看来,被称为OnMeasureItem时,columnNames.Length始终为0,所以列宽[colIndex]从不设置。我添加了(columnWidths.Length==0) InitializeColumns()到OnMeasureItem,但被称为OnDrawItem时,在列宽值[colIndex]均为零。为什么会发生?
kiennt
评论会员:游客 时间:2011/12/14
嗨我的朋友,你必须改变OnDataSourceChanged从保护覆盖无效OnDataSourceChanged(级E){base.OnDataSourceChanged(E);InitializeColumns() }保护覆盖无效OnDataSourceChanged(级E){InitializeColumns() base.OnDataSourceChanged(E); }