最近有个难题,比较棘手,是关于datagrid的每一行绑定的combobox的下拉列表有可能会不一样,这该如何搞定 vs2003(winform)

时间:2021-10-10 23:00:01
DataGridComboBoxColumn类

using System;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Data;

namespace Microsoft.Msdn.Article.DataGridColumnStyles.DownloadManager {

public class DataGridComboBoxColumn : DataGridColumnStyle {

private ComboBox m_comboBox;
private int m_previouslyEditedCellRow;
private DataGridColumnStylePadding m_padding;
private string displayMember,valueMember;

public DataGridComboBoxColumn(ComboBox m_comboBox,string displayMember,string valueMember) : base() {

this.m_comboBox = m_comboBox;
this.displayMember = displayMember;
this.valueMember = valueMember;
//m_comboBox = new ComboBox();
this.m_comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
this.m_comboBox.Visible = false;
this.m_comboBox.SizeChanged += new EventHandler( ComboBox_SizeChanged );

this.ControlSize = m_comboBox.Size;
this.Padding = new DataGridColumnStylePadding( 0, 0, 0, 0 );
this.Width = this.GetPreferredSize( null, null ).Width;

//this.m_comboBox.SelectedIndex = 0;

}

public ComboBox ComboBox {
get { return m_comboBox; }
}

public DataGridColumnStylePadding Padding {
get { return m_padding; }
set { m_padding = value; }
}

public Size ControlSize {
get { return m_comboBox.Size; }
set { m_comboBox.Size = value; }
}

protected override void Abort(int rowNum) {

// reset combobox
m_comboBox.Visible = false;

}

protected override void Edit(CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible) {

Debug.WriteLine( "ComboBox Edit" );

// get cursor coordinates
Point p = this.DataGridTableStyle.DataGrid.PointToClient( Cursor.Position );

// get control bounds
Rectangle controlBounds = this.GetControlBounds( bounds );

// get cursor bounds
Rectangle cursorBounds = new Rectangle( p.X, p.Y, 1, 1 );


 m_comboBox.SelectedIndex = ( int ) this.GetColumnValueAtRow( source, rowNum );

Debug.WriteLine( "SelectedItem: " + m_comboBox.SelectedIndex );
m_comboBox.Location = new Point( controlBounds.X, controlBounds.Y );
m_comboBox.Visible = true;

if ( cursorBounds.IntersectsWith( controlBounds ) ) {
m_comboBox.DroppedDown = true;
}

m_previouslyEditedCellRow = rowNum;

}

protected override bool Commit( CurrencyManager dataSource, int rowNum ) {

if ( m_previouslyEditedCellRow == rowNum ) {
this.SetColumnValueAtRow( dataSource, rowNum, m_comboBox.SelectedIndex );
}

m_comboBox.Visible = false;

return true;

}

protected override void SetDataGridInColumn( DataGrid value ) {

base.SetDataGridInColumn( value );

if ( !value.Controls.Contains( m_comboBox ) ) {
value.Controls.Add( m_comboBox );
}

}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum, System.Drawing.Brush backBrush, System.Drawing.Brush foreBrush, bool alignToRight) {

g.FillRectangle( new SolidBrush( Color.White ), bounds );

StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Center;

Rectangle controlBounds = this.GetControlBounds( bounds );

int colValue = ( int ) this.GetColumnValueAtRow( source, rowNum );

string selectedItem = (((DataRowView)m_comboBox.Items[ colValue  ])[displayMember]).ToString();

Rectangle textRegion = new Rectangle( 
controlBounds.X + 1,
controlBounds.Y + 4,
controlBounds.Width - 3,
( int ) g.MeasureString( selectedItem, m_comboBox.Font ).Height );

g.DrawString( selectedItem, m_comboBox.Font, foreBrush, textRegion, sf );

ControlPaint.DrawBorder3D( g, controlBounds, Border3DStyle.Sunken );

Rectangle buttonBounds = controlBounds;
buttonBounds.Inflate( -2, -2 );

ControlPaint.DrawComboButton( 
g, 
buttonBounds.X + ( controlBounds.Width - 20 ), 
buttonBounds.Y, 
16, 
17, 
ButtonState.Normal );

}

private void ComboBox_SizeChanged(object sender, EventArgs e) {

this.ControlSize = m_comboBox.Size;
this.Width = this.GetPreferredSize( null, null ).Width;
this.Invalidate();

}

private Rectangle GetControlBounds( Rectangle cellBounds ) {

Rectangle controlBounds = new Rectangle( 
cellBounds.X + this.Padding.Left, 
cellBounds.Y + this.Padding.Top, 
this.ControlSize.Width,
this.ControlSize.Height );

return controlBounds;

}

#region The rest of the DataGridColumnStyle methods

protected override int GetMinimumHeight() {
return GetPreferredHeight( null, null );
}

protected override int GetPreferredHeight(System.Drawing.Graphics g, object value) {
return this.ControlSize.Height + this.Padding.Top + this.Padding.Bottom;
}

protected override System.Drawing.Size GetPreferredSize(System.Drawing.Graphics g, object value) {

int width = this.ControlSize.Width + this.Padding.Left + this.Padding.Right;
int height = this.ControlSize.Height + this.Padding.Top + this.Padding.Bottom;

return new Size( width, height );

}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum) {
this.Paint( g, bounds, source, rowNum, false );
}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight) {
this.Paint( g, bounds, source, rowNum, Brushes.White, Brushes.Black, false );
}

#endregion The rest of the DataGridColumnStyle methods


}

}

DataGridColumnStylePadding类

using System;
using System.ComponentModel;

namespace Microsoft.Msdn.Article.DataGridColumnStyles {

public class DataGridColumnStylePadding {

int m_left;
int m_right;
int m_top;
int m_bottom;

public int Left {
get { return m_left; }
set { m_left = value; }
}

public int Right {
get { return m_right; }
set { m_right = value; }
}

public int Top {
get { return m_top; }
set { m_top = value; }
}

public int Bottom {
get { return m_bottom; }
set { m_bottom = value; }
}

public void SetPadding( int padValue ) {

m_left = padValue;
m_right = padValue;
m_top = padValue;
m_bottom = padValue;

}

public void SetPadding( int top, int right, int bottom, int left ) {
UpdatePaddingValues( top, right, bottom, left );
}

public DataGridColumnStylePadding( int padValue ) {
this.SetPadding( padValue );
}

public DataGridColumnStylePadding( int top, int right, int bottom, int left ) {
UpdatePaddingValues( top, right, bottom, left );
}

private void UpdatePaddingValues( int top, int right, int bottom, int left ) {

m_top = top;
m_right = right;
m_bottom = bottom;
m_left = left;

}

}

}


以上是我用的微软的一个例子,且修改为可以绑定数据源的combobox

datagrid里建立一个此类型的列,将comboBox加入到此列,并绑定数据源

如果说下拉框都相同,很简单可以实现,但是事实是一个调查表,所以选项肯定可能都相同,我现在都快要放弃DataGrid了,都想用控件自动生成一张由label,和下拉的调查表了,微软的DataGrid好难实现复杂功能,由于掌握得比较肤浅,所以无法驾驭,但是DevExpress的xTraGrid又太复杂,唉,有哪位高手能帮我指点一下呢?

谢谢!

13 个解决方案

#1


可以判断一下是点击的哪一行,然后再根据条件给combbox加不同的items

#2


如果数据不相同,是否合绑定的列有什么关系

#3


三只熊熊 :你的方法我想过,我传给那个列的ComboBox是一个实例,点击一个变化的话,都会变的啊,其它行的选项不就又变化了?

Knight94(愚翁) ( )
比如说第一行我的下拉应该是 
|很好|
|不错|
|一般|
|差|

第二行是
|严重|
|还行|
|不行|

#4


一年前做过,现在记不得了,呵呵

#5


楼上的哥们难道也是点击一行再对DataView重新绑定?然后把选中的值存在隐藏的Column里?

我一开始就是这么想的,但是觉得微软搞这么个半成品给我们用,是比较郁闷的。。

#6


关注。。。学习。。。帮你顶。。。

#7


其实这不是微软的问题,就你所给出的例子,是把不同组合数据用同一列来表明,这首先在数据库设计上连范式一都满足不了。

如果你的combox列和某些信息与其他表有外键关联信息的话,是可以做的。

#8


Knight94(愚翁) 

是这样子的。

答案组表
|QID| |QName|
 1    答案组1
 2    答案组2

选项组表
|id| |QID| |AName| |Percent|
 1    1     很好    80%
 2    1     不错    60%
 3    1     一般    40%
 4    1     差      20%
 5    2     严重    100%
 6    2     还行    60%
 7    2     不行    20%

DataTable中有一列是QID,如果说是直接显示选项组还是很简单的,关键怎么根据行不同,下拉列表的值也不同呢,对DataGrid了解还很肤浅,所以要提这个问题了,微软那个例子的确给我改成一个ComboBox实例来显示不同的数值肯定是不行的,那么要怎么改呢?

#9


to DataTable中有一列是QID,如果说是直接显示选项组还是很简单的,关键怎么根据行不同,下拉列表的值也不同呢,对DataGrid了解还很肤浅,所以要提这个问题了,微软那个例子的确给我改成一个ComboBox实例来显示不同的数值肯定是不行的,那么要怎么改呢

你不是写了个了DataGridComboBoxColumn,那么在获得焦点的时候,对combobox进行重新绑定不就行了,例如:
DataView dv = new DataView( yourDataTable, rowfilter, null, ... );
//use "dv" to bind your combobox

#10


你不是写了个了DataGridComboBoxColumn,那么在获得焦点的时候,对combobox进行重新绑定不就行了,例如:
DataView dv = new DataView( yourDataTable, rowfilter, null, ... );
//use "dv" to bind your combobox
==============
获得焦点时重新绑定会影响其它的行里的combobox啊。我本来选择好的其它行的ComboBox不是跟着变化了吗?

#11


to 获得焦点时重新绑定会影响其它的行里的combobox啊。我本来选择好的其它行的ComboBox不是跟着变化了吗?

谁获的焦点,根据条件设置新的combobox数据,没获得焦点,当然不会进行改变。

#12


我原来只能绑定一个死的DataView,我试试RowFilter。

#13


遇到同样的问题。
关注。

#1


可以判断一下是点击的哪一行,然后再根据条件给combbox加不同的items

#2


如果数据不相同,是否合绑定的列有什么关系

#3


三只熊熊 :你的方法我想过,我传给那个列的ComboBox是一个实例,点击一个变化的话,都会变的啊,其它行的选项不就又变化了?

Knight94(愚翁) ( )
比如说第一行我的下拉应该是 
|很好|
|不错|
|一般|
|差|

第二行是
|严重|
|还行|
|不行|

#4


一年前做过,现在记不得了,呵呵

#5


楼上的哥们难道也是点击一行再对DataView重新绑定?然后把选中的值存在隐藏的Column里?

我一开始就是这么想的,但是觉得微软搞这么个半成品给我们用,是比较郁闷的。。

#6


关注。。。学习。。。帮你顶。。。

#7


其实这不是微软的问题,就你所给出的例子,是把不同组合数据用同一列来表明,这首先在数据库设计上连范式一都满足不了。

如果你的combox列和某些信息与其他表有外键关联信息的话,是可以做的。

#8


Knight94(愚翁) 

是这样子的。

答案组表
|QID| |QName|
 1    答案组1
 2    答案组2

选项组表
|id| |QID| |AName| |Percent|
 1    1     很好    80%
 2    1     不错    60%
 3    1     一般    40%
 4    1     差      20%
 5    2     严重    100%
 6    2     还行    60%
 7    2     不行    20%

DataTable中有一列是QID,如果说是直接显示选项组还是很简单的,关键怎么根据行不同,下拉列表的值也不同呢,对DataGrid了解还很肤浅,所以要提这个问题了,微软那个例子的确给我改成一个ComboBox实例来显示不同的数值肯定是不行的,那么要怎么改呢?

#9


to DataTable中有一列是QID,如果说是直接显示选项组还是很简单的,关键怎么根据行不同,下拉列表的值也不同呢,对DataGrid了解还很肤浅,所以要提这个问题了,微软那个例子的确给我改成一个ComboBox实例来显示不同的数值肯定是不行的,那么要怎么改呢

你不是写了个了DataGridComboBoxColumn,那么在获得焦点的时候,对combobox进行重新绑定不就行了,例如:
DataView dv = new DataView( yourDataTable, rowfilter, null, ... );
//use "dv" to bind your combobox

#10


你不是写了个了DataGridComboBoxColumn,那么在获得焦点的时候,对combobox进行重新绑定不就行了,例如:
DataView dv = new DataView( yourDataTable, rowfilter, null, ... );
//use "dv" to bind your combobox
==============
获得焦点时重新绑定会影响其它的行里的combobox啊。我本来选择好的其它行的ComboBox不是跟着变化了吗?

#11


to 获得焦点时重新绑定会影响其它的行里的combobox啊。我本来选择好的其它行的ComboBox不是跟着变化了吗?

谁获的焦点,根据条件设置新的combobox数据,没获得焦点,当然不会进行改变。

#12


我原来只能绑定一个死的DataView,我试试RowFilter。

#13


遇到同样的问题。
关注。