C# DataGridView:组合框设置
我有一个简单的2表设置,“团队”和“球员”。每个玩家都有一个(可为空的)int-TeamID(首选AllowDBNull,但默认值为-1也可以)。 我在两个表中插入/更新/删除记录,这些记录都是可靠的(小测试数据库中的mathich ID)。 设置如下所示:C# DataGridView:组合框设置,c#,winforms,datatable,datagridview,datagridviewcombobox,C#,Winforms,Datatable,Datagridview,Datagridviewcombobox,我有一个简单的2表设置,“团队”和“球员”。每个玩家都有一个(可为空的)int-TeamID(首选AllowDBNull,但默认值为-1也可以)。 我在两个表中插入/更新/删除记录,这些记录都是可靠的(小测试数据库中的mathich ID)。 设置如下所示: private void initDataSet() { dataSet = new DataSet( "DataBase" ); var dtPlayers = new DataTable( &quo
private void initDataSet()
{
dataSet = new DataSet( "DataBase" );
var dtPlayers = new DataTable( "Players" );
dtPlayers.Columns.Add( new DataColumn() {
ColumnName = "ID" ,
Caption = "ID" ,
DataType = typeof( int ) ,
Unique = true ,
AutoIncrement = true ,
} );
dtPlayers.Columns.Add( new DataColumn() {
ColumnName = "TeamID" ,
Caption = "Team" ,
DataType = typeof( int ) ,
//AllowDBNull = true ,
//DefaultValue = DBNull.Value ,
} );
dataSet.Tables.Add( dtPlayers );
var dtTeams = new DataTable( "Teams" );
dtTeams.Columns.Add( new DataColumn() {
ColumnName = "ID" ,
Caption = "ID" ,
DataType = typeof( int ) ,
Unique = true ,
AutoIncrement = true ,
} );
dtTeams.Columns.Add( new DataColumn() {
ColumnName = "FullName" ,
Caption = "Full Name" ,
DataType = typeof( string ) ,
} );
dataSet.Tables.Add( dtTeams );
dtPlayers.PrimaryKey = new DataColumn[] { dtPlayers.Columns[ "ID" ] };
dtTeams.PrimaryKey = new DataColumn[] { dtTeams.Columns[ "ID" ] };
dataSet.Relations.Add( "Team - Player" , dtTeams.Columns[ "ID" ] , dtPlayers.Columns[ "TeamID" ] );
}
现在我想用一个下拉列表来显示players表中的球队,默认选择为空(意味着没有球队被选中-值为r-1或null,稍后会变成DBNull)。
为此,我为DataGridViewComboBoxColumn设置了DataGridView和一个附加的DataTable作为.DataSource
。
每次选择/编辑下拉列表时,我都会更新dtTeamIds表以反映更改。
我还设置了适当的.DisplayMember
和.ValueMember
字段
private DataTable dtTeamIds = new DataTable( "TeamIds" ); // datasource for dorpdown-list only
private void updateTeamIds()
{
var teamsTable = dataSet.Tables[ "Teams" ] as DataTable;
var items = teamsTable.Rows.Cast<DataRow>()
.Select( row => new KeyValuePair<string,int>(
row.Field<string>( "FullName" ) ,
row.Field<int>( "ID" ) ) )
.Prepend( new KeyValuePair<string , int>( "---" , -1 ) )
.ToArray();
dtTeamIds.Rows.Clear();
foreach( var item in items )
{
var row = dtTeamIds.NewRow();
row.SetField( dtTeamIds.Columns[ "MyValue" ] , item.Value );
row.SetField( dtTeamIds.Columns[ "MyText" ] , item.Key );
dtTeamIds.Rows.Add( row );
}
}
private void initDataGridViews()
{
// Players
{
var dgv = dataGridViewPlayers;
dgv.AutoGenerateColumns = false;
dgv.CausesValidation = false;
var sourceTable = dataSet.Tables[ "Players" ];
var dataSrc = sourceTable;
dgv.Columns.Clear();
dgv.DataSource = new BindingSource() {
DataSource = dataSrc ,
};
dgv.Columns.Add( new DataGridViewTextBoxColumn() {
DataPropertyName = "ID" ,
Visible = false ,
} );
// dowpdown-list
{
dtTeamIds.Columns.Add( "MyText" );
dtTeamIds.Columns.Add( "MyValue" );
updateTeamIds();
dgv.Columns.Add( new DataGridViewComboBoxColumn() {
DataPropertyName = "TeamID" ,
HeaderText = dataSrc.Columns[ "TeamID" ].Caption ,
ToolTipText = "Press 'CTRL + 0' do delete the team!" ,
ValueType = typeof( int ) ,
DisplayMember = "MyText" ,
ValueMember = "MyValue" ,
DataSource = new BindingSource( dtTeamIds , null ) ,
} );
}
SetupDataGridViewDefaults( dgv );
// HACK: see: https://social.msdn.microsoft.com/Forums/en-US/243da031-760d-4e7f-b09f-be4cfa5a6a4b
dataSrc.ColumnChanging += ( s , e ) => {
if( e.Column == dataSrc.Columns[ "TeamID" ] )
{
var t2 = e.ProposedValue.GetType();
if( e.ProposedValue == null || ( e.ProposedValue is int val && val == -1 ) )
{
//e.ProposedValue = DBNull.Value; // -1 or NULL
}
}
};
//dgv.CellEnter += ( s , e ) => {
// if( e.ColumnIndex == dgv.Columns[ "TeamID" ].Index )
// {
// updateTeamIds();
// }
//};
//dgv.CellBeginEdit += ( s , e ) => {
// if( e.ColumnIndex == dgv.Columns[ "TeamID" ].Index )
// {
// updateTeamIds();
// }
//};
dgv.Click += ( s , e ) => {
updateTeamIds();
//if( e.ColumnIndex == dgv.Columns[ "TeamID" ].Index )
//{
// var cell = dgv[ e.ColumnIndex , e.RowIndex ] as DataGridViewComboBoxCell;
//}
};
dgv.CellFormatting += ( s , e ) => {
if( e.ColumnIndex == dgv.Columns[ "TeamID" ].Index )
{
var cell = dgv[ e.ColumnIndex , e.RowIndex ] as DataGridViewComboBoxCell;
//var _1 = cell.EditedFormattedValue;
//var _2 = cell.FormattedValue;
var _3 = cell.Value; // null
var _4 = e.Value; // null
var _5 = e.DesiredType; // string
}
};
}
// setup teams-table etc..
}
private void SetupDataGridViewDefaults( DataGridView dgv )
{
// TODO: figure out how to properly resize columns
foreach( var colIdx in Enumerable.Range( 0 , dgv.Columns.Count ) )
{
var col = dgv.Columns[ colIdx ];
col.Name = col.DataPropertyName;
col.MinimumWidth = 50;
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
if( colIdx == dgv.Columns.Count - 1 )
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
col.Width = col.Width; //This is important, otherwise the following line will nullify your previous command
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
}
dgv.AutoResizeColumns( DataGridViewAutoSizeColumnsMode.AllCells );
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dgv.Columns[ dgv.Columns.Count - 1 ].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dgv.AllowUserToResizeColumns = true;
dgv.AllowUserToOrderColumns = false;
dgv.AllowUserToResizeRows = true;
dgv.Enabled = true;
dgv.Refresh();
}
私有数据表dtTeamIds=新数据表(“TeamIds”);//仅适用于dorpdown列表的数据源
私有void updatetamids()
{
var teamsTable=dataSet.Tables[“Teams”]作为DataTable;
var items=teamsTable.Rows.Cast()
.选择(行=>new KeyValuePair(
行字段(“全名”),
行。字段(“ID”))
.Prepend(新的KeyValuePair(“--”和-1))
.ToArray();
dtTeamIds.Rows.Clear();
foreach(项目中的var项目)
{
var row=dtTeamIds.NewRow();
row.SetField(dtTeamIds.Columns[“MyValue”]、item.Value);
row.SetField(dtTeamIds.Columns[“MyText”],item.Key);
dtTeamIds.Rows.Add(row);
}
}
私有void initDataGridViews()
{
//球员
{
var dgv=DataGridViewPlayer;
dgv.AutoGenerateColumns=false;
dgv.CausesValidation=false;
var sourceTable=dataSet.Tables[“Players”];
var-dataSrc=sourceTable;
dgv.Columns.Clear();
dgv.DataSource=newbindingsource(){
DataSource=dataSrc,
};
添加(新的DataGridViewTextBoxColumn(){
DataPropertyName=“ID”,
可见=假,
} );
//dowpdown列表
{
dtTeamIds.Columns.Add(“MyText”);
dtTeamIds.Columns.Add(“MyValue”);
updatetamids();
添加(新的DataGridViewComboxColumn(){
DataPropertyName=“TeamID”,
HeaderText=dataSrc.Columns[“TeamID”]。标题,
ToolTipText=“按“CTRL+0”确实删除团队!”,
ValueType=typeof(int),
DisplayMember=“MyText”,
ValueMember=“MyValue”,
DataSource=新的BindingSource(DTTeamID,null),
} );
}
SetupDataGridViewDefaults(dgv);
//黑客:见:https://social.msdn.microsoft.com/Forums/en-US/243da031-760d-4e7f-b09f-be4cfa5a6a4b
dataSrc.ColumnChanging+=(s,e)=>{
if(e.Column==dataSrc.Columns[“TeamID”])
{
var t2=e.ProposedValue.GetType();
如果(e.ProposedValue==null | |(e.ProposedValue为int val&&val=-1))
{
//e、 ProposedValue=DBNull.Value;//-1或NULL
}
}
};
//dgv.CellEnter+=(s,e)=>{
//如果(e.ColumnIndex==dgv.Columns[“TeamID”].Index)
// {
//updatetamids();
// }
//};
//dgv.CellBeginEdit+=(s,e)=>{
//如果(e.ColumnIndex==dgv.Columns[“TeamID”].Index)
// {
//updatetamids();
// }
//};
dgv.单击+=(s,e)=>{
updatetamids();
//如果(e.ColumnIndex==dgv.Columns[“TeamID”].Index)
//{
//var cell=dgv[e.ColumnIndex,e.RowIndex]作为DataGridViewComboxCell;
//}
};
dgv.CellFormatting+=(s,e)=>{
如果(e.ColumnIndex==dgv.Columns[“TeamID”].Index)
{
var cell=dgv[e.ColumnIndex,e.RowIndex]作为DataGridViewComboxCell;
//var_1=cell.EditedFormattedValue;
//var_2=cell.FormattedValue;
var _3=cell.Value;//null
var _4=e.Value;//null
var _5=e.DesiredType;//字符串
}
};
}
//设置团队表等。。
}
专用void设置DataGridViewDefaults(DataGridView dgv)
{
//TODO:了解如何正确调整列的大小
foreach(可枚举范围(0,dgv.Columns.Count)中的var colIdx)
{
var col=dgv.Columns[colIdx];
col.Name=col.DataPropertyName;
柱最小宽度=50;
col.AutoSizeMode=DataGridViewAutoSizeColumnMode.AllCells;
if(colIdx==dgv.Columns.Count-1)
col.AutoSizeMode=DataGridViewAutoSizeColumnMode.Fill;
col.Width=col.Width;//这很重要,否则下一行将使上一个命令无效
col.AutoSizeMode=DataGridViewAutoSizeColumnMode.NotSet;
}
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
dgv.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.None;
dgv.Columns[dgv.Columns.Count-1].AutoSizeMode=DataGridViewAutoSizeColumnMode.Fill;
dgv.AllowUserToResizeColumns=true;
dgv.AllowUserToOrderColumns=false;
dgv.AllowUserToResizeRows=true;
dgv.Enabled=true;
dgv.Refresh();
}
现在,当我启动应用程序时,最初下拉列表是空的(没有选择,不是“---”)。
编辑组合框单元格时,将显示团队和默认的“--”,顶部的选定项将成为“--”项。
在对团队的combobox单元格进行任何更改后,单击任何其他单元格时,我会得到一个FormatException(CBox单元格值无效)
我试图获取有关该值无效的位置或原因的信息,检查CellBegin/EndEdit、Formattin、Changed等事件
private DataTable GetTeamsComboDT() {
DataTable teams = dataSet.Tables["Teams"].Copy();
teams.TableName = "TeamsComboDT";
DataTable players = dataSet.Tables["Players"];
List<int> teamIDs = new List<int>();
foreach (DataRow row in teams.Rows) {
if (row["ID"] != null && !teamIDs.Contains((int)row["ID"])) {
teamIDs.Add((int)row["ID"]);
}
}
foreach (DataRow row in players.Rows) {
if (row["TeamID"] != DBNull.Value && !teamIDs.Contains((int)row["TeamID"])) {
teams.Rows.Add((int)row["TeamID"], "Team " + (int)row["TeamID"] + " ???");
teamIDs.Add((int)row["TeamID"]);
}
}
DataRow emptyRow = teams.NewRow();
emptyRow["ID"] = DBNull.Value;
emptyRow["FullName"] = "---";
teams.Rows.InsertAt(emptyRow, 0);
return teams;
}
private DataGridViewComboBoxColumn GetTeamsComboCol() {
DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn();
col.HeaderText = "Team";
col.Name = "Teams";
col.DataPropertyName = "TeamID";
col.ValueMember = "ID";
col.DisplayMember = "FullName";
col.DataSource = dataSet.Tables["TeamsComboDT"];
return col;
}
private void FillTeamsTable() {
DataTable dt = dataSet.Tables["Teams"];
for (int i = 0; i < 10; i++) {
dt.Rows.Add(i + 1, "Team " + (i + 1).ToString());
}
}
private void FillPlayersTable() {
DataTable dt = dataSet.Tables["Players"];
Random rand = new Random();
int randTeam;
for (int i = 0; i < 25; i++) {
randTeam = rand.Next(0, 12);
switch (randTeam) {
case 0:
dt.Rows.Add(i + 1, DBNull.Value);
break;
case 11:
dt.Rows.Add(i + 1, 22);
break;
default:
dt.Rows.Add(i + 1, randTeam);
break;
}
}
}
DataSet dataSet;
public Form2() {
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e) {
dataSet = new DataSet();
AddTeamsDT_ToDS();
AddPlayerDT_ToDS();
FillTeamsTable();
FillPlayersTable();
dataSet.Tables.Add(GetTeamsComboDT());
dataGridView1.Columns.Add(GetTeamsComboCol());
dataGridView1.DataSource = dataSet.Tables["Players"];
dataGridView1.Columns["Teams"].DisplayIndex = 1;
}
private void AddPlayerDT_ToDS() {
DataTable dt = new DataTable("Players");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("TeamID", typeof(int));
dataSet.Tables.Add(dt);
}
private void AddTeamsDT_ToDS() {
DataTable dt = new DataTable("Teams");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("FullName", typeof(string));
dataSet.Tables.Add(dt);
}