DataGrid是可以绑定ComboBox来进行选择某一列的值,但是有时候选项太多,或者通过一列数据无法完全说明选项含义的时候,就希望来弹出一个窗口,来对子项进行更充分的说明,以供选择。
我下面的例子就是说明如何实现一个弹出窗口来对子项进行选择。
首先,继承DataGridTextBoxColumn来定义自己的数据列,具体如下:
public delegate string PopupWindow();
public class DataGridPopupColumn: DataGridTextBoxColumn
{
private Panel pnlPopup;//Basic control for column
private System.Windows.Forms.CurrencyManager _source = null;
private int _rowNum;
public static int _RowCount = -1;
PopupWindow PopupWindowHandle;
public DataGridPopupColumn( PopupWindow ShowPopupWindow ) : base()
{
// Init class members
PopupWindowHandle = ShowPopupWindow;
pnlPopup = new Panel();
// Define event handler
pnlPopup.Leave += new EventHandler( LeavePanel );
pnlPopup.Click += new EventHandler( ClickPanel );
pnlPopup.Paint += new PaintEventHandler( PaintPanel );
}
private void LeavePanel( object sender, EventArgs e )
{
pnlPopup.Hide();//Hide panel
}
private void ClickPanel( object sender, EventArgs e )
{
// Show a window to select value
object objReturn = this.pnlPopup.Parent.Invoke( PopupWindowHandle );
if( objReturn != null )
{
// Get value from window result
this.TextBox.Text = objReturn.ToString();
// Save it to data source
SetColumnValueAtRow( _source, _rowNum, this.TextBox.Text);
// Re-draw panel
this.pnlPopup.Refresh();
Invalidate();
}
}
private void PaintPanel( object sender, System.Windows.Forms.PaintEventArgs e)
{
// Set panel size
pnlPopup.Width = this.TextBox.Width;
pnlPopup.Height = this.TextBox.Height;
// Draw back ground same as current cell
Graphics gPanel = e.Graphics;
gPanel.FillRectangle( new SolidBrush( this.TextBox.BackColor ),
0,0, this.pnlPopup.Width, this.pnlPopup.Height );
// Draw text in panel
StringFormat sfText = new StringFormat();
sfText.Alignment = StringAlignment.Near;
sfText.LineAlignment = StringAlignment.Center;
gPanel.DrawString(
this.TextBox.Text,
this.TextBox.Font,
new SolidBrush( this.TextBox.ForeColor ),
new Rectangle( new Point( 0, 0 ),
new Size( pnlPopup.Width, pnlPopup.Height ) ),
sfText );
// Draw a triangle in the right side of panel
SolidBrush sbBlack = new SolidBrush( Color.Black );
const float TRI_HEIGHT = 6F;
PointF[] ptTriangle = new PointF[3]{
new PointF( pnlPopup.Width - 5 - 12, ( pnlPopup.Height - TRI_HEIGHT ) / 2 ),
new PointF( pnlPopup.Width - 5 , ( pnlPopup.Height - TRI_HEIGHT ) / 2 ),
new PointF( pnlPopup.Width - 5 - 6, ( pnlPopup.Height + TRI_HEIGHT ) / 2 )
};
gPanel.FillPolygon( sbBlack, ptTriangle );
}
protected override void Edit( System.Windows.Forms.CurrencyManager source,
int rowNum, System.Drawing.Rectangle bounds,
bool readOnly, string instantText, bool cellIsVisible )
{
//on very first pass, set this static member to number of items in tables
if(_RowCount == -1)
_RowCount = source.Count;
//check to see if we are on the new row
if(_RowCount < source.Count)
{
// remove the one that has been added
// and add a new to sync
source.RemoveAt(source.Count-1);
source.AddNew();
}
_RowCount = source.Count;
base.Edit(source,rowNum, bounds, readOnly, instantText , cellIsVisible);
_rowNum = rowNum;
_source = source;
// Init panel
pnlPopup.Parent = this.TextBox.Parent;
pnlPopup.Location = this.TextBox.Location;
pnlPopup.Size = new Size(this.TextBox.Size.Width, this.TextBox.Size.Height);
// Show panel
pnlPopup.Invalidate();// Modified by Knight on Apr.18, 2006
pnlPopup.Visible = true;
pnlPopup.BringToFront();
}
protected override bool Commit( System.Windows.Forms.CurrencyManager dataSource,
int rowNum )
{
return true;
}
}
主窗体调用如下。
/// <summary>
/// A method declared for popup-column
/// </summary>
/// <returns></returns>
private string PopupWindow()
{
frmPopup myPopup = new frmPopup();
if( myPopup.ShowDialog() == DialogResult.OK )
return myPopup.SelectedItem;
else
return null;
}
private void CreateEmployeeTable( out DataTable dtEmployee )
{
dtEmployee = new DataTable();
dtEmployee.TableName = "EmployeeInfo";
//Set data columns
dtEmployee.Columns.Add( "EmployeeID", typeof( int ) );
dtEmployee.Columns.Add( "Department", typeof( string ) );
dtEmployee.Columns.Add( "Name", typeof( string ) );
dtEmployee.Columns.Add( "Phone", typeof( string ) );
dtEmployee.Columns.Add( "Address", typeof( string ) );
// Add data
dtEmployee.Rows.Add( new object[]{ 1, "Sales", "Sales1", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 2, "Sales", "Sales2", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 3, "HR", "HR1", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 4, "HR", "HR2", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 5, "Tech", "Tech1", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 6, "Tech", "Tech2", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 7, "Software", "Software1", "*****","*****" } );
dtEmployee.Rows.Add( new object[]{ 8, "Software", "Software2", "*****","*****" } );
}
private void CreateDataSet()
{
myDataSet = new DataSet();
DataTable dtEmployee;
CreateEmployeeTable( out dtEmployee );
myDataSet.Tables.Add( dtEmployee );
}
private void AddTableStyle()
{
DataGridTableStyle ts1 = new DataGridTableStyle();
ts1.MappingName = "EmployeeInfo";
DataGridTextBoxColumn TextCol = new DataGridTextBoxColumn();
TextCol.MappingName = "EmployeeID";
TextCol.HeaderText = "Employee ID";
TextCol.Width = 80;
ts1.GridColumnStyles.Add(TextCol);
// Add popup column with event method
DataGridPopupColumn PopupTextCol = new DataGridPopupColumn(
new PopupWindow( PopupWindow ) );
PopupTextCol.MappingName = "Department";
PopupTextCol.HeaderText = "Department";
PopupTextCol.Width = 100;
ts1.GridColumnStyles.Add( PopupTextCol );
TextCol = new DataGridTextBoxColumn();
TextCol.MappingName = "Name";
TextCol.HeaderText = "Name";
TextCol.Width = 100;
ts1.GridColumnStyles.Add(TextCol);
TextCol = new DataGridTextBoxColumn();
TextCol.MappingName = "Phone";
TextCol.HeaderText = "Phone";
TextCol.Width = 100;
ts1.GridColumnStyles.Add(TextCol);
TextCol = new DataGridTextBoxColumn();
TextCol.MappingName = "Address";
TextCol.HeaderText = "Address";
TextCol.Width = 150;
ts1.GridColumnStyles.Add(TextCol);
//add the custom table style to the datagrid table styles
dtgUserInfo.TableStyles.Add(ts1);
}
private void BindData()
{
CreateDataSet();
dtgUserInfo.SetDataBinding( myDataSet, "EmployeeInfo");
AddTableStyle();
}
private void frmComboxDB_Load(object sender, System.EventArgs e)
{
BindData();
}
最后,就是弹出窗口的代码,这部分由于需求不一样,做法可以千变万化,以下只是一个简单的例子,即在一个ListBox进行选择。
public string SelectedItem
{
get{
if( lstDepInfo.SelectedItem != null )
return lstDepInfo.SelectedItem.ToString();
else
return null;
}
}
private void frmPopup_Load(object sender, System.EventArgs e)
{
lstDepInfo.Items.Add( "Sales" );
lstDepInfo.Items.Add( "HR" );
lstDepInfo.Items.Add( "Tech" );
lstDepInfo.Items.Add( "Software" );
}
private void btnOK_Click(object sender, System.EventArgs e)
{
this.DialogResult = DialogResult.OK;
}
private void btnCancel_Click(object sender, System.EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
}