以下是C# DataGridView应用的综合实现方案,满足所有需求:
一、核心功能实现
public partial class MainForm : Form
{
private DataTable dataTable = new DataTable();
private DataTable followTable = new DataTable();
private const string MaskedValue = "******";
public MainForm()
{
InitializeComponent();
InitializeDataTables();
ConfigureDataGridView();
}
// 初始化数据表
private void InitializeDataTables()
{
// 主表
dataTable.Columns.Add("ID", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
dataTable.Columns.Add("Password", typeof(string)); // 需掩码字段
dataTable.Columns.Add("BirthDate", typeof(DateTime));
dataTable.Columns.Add("Salary", typeof(decimal));
dataTable.Columns.Add("Status", typeof(string));
// 跟进表
followTable.Columns.Add("FollowID", typeof(int));
followTable.Columns.Add("MainID", typeof(int)); // 关联主表ID
followTable.Columns.Add("FollowDate", typeof(DateTime));
followTable.Columns.Add("Content", typeof(string));
followTable.Columns.Add("Recorder", typeof(string));
followTable.Columns.Add("Status", typeof(string));
followTable.Columns.Add("Reminder", typeof(DateTime));
}
// 配置DataGridView
private void ConfigureDataGridView()
{
dataGridView1.DataSource = dataTable;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToOrderColumns = true; // 自选列
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
// 设置密码列掩码
dataGridView1.CellFormatting += (s, e) =>
{
if (e.ColumnIndex == dataGridView1.Columns["Password"].Index && e.Value != null)
{
e.Value = MaskedValue;
e.FormattingApplied = true;
}
};
// 双击事件
dataGridView1.CellDoubleClick += DataGridView1_CellDoubleClick;
}
// 双击事件处理
private void DataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;
// 密码列显示真实值
if (e.ColumnIndex == dataGridView1.Columns["Password"].Index)
{
var cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
cell.Value = dataTable.Rows[e.RowIndex]["Password"];
return;
}
// 行双击显示详情窗口
ShowDetailForm(e.RowIndex);
}
// 显示详情窗口
private void ShowDetailForm(int rowIndex)
{
var row = dataTable.Rows[rowIndex];
using (var detailForm = new DetailForm(row, followTable))
{
detailForm.ShowDialog();
}
}
}
二、详情窗口实现(DetailForm.cs)
public partial class DetailForm : Form
{
private DataRow mainRow;
private DataTable followTable;
public DetailForm(DataRow row, DataTable followTable)
{
InitializeComponent();
this.mainRow = row;
this.followTable = followTable;
DisplayMainData();
LoadFollowRecords();
}
// 显示主表数据
private void DisplayMainData()
{
// 动态创建控件
int yPos = 20;
foreach (DataColumn column in mainRow.Table.Columns)
{
var lbl = new Label { Text = column.ColumnName + ":", Location = new Point(20, yPos) };
Control valueControl;
switch (column.DataType.Name)
{
case "DateTime":
valueControl = new DateTimePicker()
{
Value = Convert.ToDateTime(mainRow[column]),
Location = new Point(150, yPos - 3)
};
break;
case "Decimal":
case "Int32":
valueControl = new NumericUpDown()
{
Value = Convert.ToDecimal(mainRow[column]),
Location = new Point(150, yPos)
};
break;
default:
valueControl = new ComboBox()
{
Text = mainRow[column].ToString(),
Location = new Point(150, yPos),
DropDownStyle = ComboBoxStyle.DropDown
};
break;
}
panelMain.Controls.Add(lbl);
panelMain.Controls.Add(valueControl);
yPos += 30;
}
}
// 加载跟进记录
private void LoadFollowRecords()
{
int mainID = Convert.ToInt32(mainRow["ID"]);
var filteredRows = followTable.Select($"MainID = {mainID}");
if (filteredRows.Length > 0)
{
dataGridViewFollow.DataSource = filteredRows.CopyToDataTable();
}
}
// 添加跟进记录
private void btnAddFollow_Click(object sender, EventArgs e)
{
var newRow = followTable.NewRow();
newRow["MainID"] = mainRow["ID"];
newRow["FollowDate"] = dateTimePickerFollow.Value;
newRow["Content"] = txtContent.Text;
newRow["Recorder"] = cmbRecorder.Text;
newRow["Status"] = cmbStatus.Text;
newRow["Reminder"] = dateTimePickerReminder.Value;
followTable.Rows.Add(newRow);
LoadFollowRecords();
}
}
三、功能说明
-
自选列功能
dataGridView1.AllowUserToOrderColumns = true;用户可直接拖动列标题调整列顺序
-
按列排序
自动支持点击列标题排序(DataTable默认绑定支持) -
字段掩码与显示
- 指定字段(如Password)显示为
****** - 双击密码单元格时显示真实值
- 使用
CellFormatting事件实现掩码:
dataGridView1.CellFormatting += (s, e) => { if (e.ColumnIndex == dataGridView1.Columns["Password"].Index) e.Value = MaskedValue; }; - 指定字段(如Password)显示为
-
行详情卡片
- 双击行头弹出详情窗口
- 动态创建控件显示数据:
- 日期字段:DateTimePicker
- 数值字段:NumericUpDown
- 字符字段:ComboBox(可编辑)
-
跟进系统
- 独立
followTable存储跟进记录 - 字段包含:
followTable.Columns.Add("FollowDate", typeof(DateTime)); followTable.Columns.Add("Content", typeof(string)); followTable.Columns.Add("Recorder", typeof(string)); followTable.Columns.Add("Status", typeof(string)); followTable.Columns.Add("Reminder", typeof(DateTime)); - 通过
MainID关联主表记录
- 独立
四、界面建议布局
| 区域 | 控件类型 | 功能说明 |
|---|---|---|
| 主窗体 | DataGridView | 显示主数据(带掩码列) |
| 详情窗口-上部 | Panel | 动态生成字段编辑控件 |
| 详情窗口-中部 | DataGridView | 显示历史跟进记录 |
| 详情窗口-下部 | GroupBox | 新增跟进输入区域 |
| 跟进区域 | DateTimePicker×2 | 跟进日期/提醒时间 |
| ComboBox×2 | 记录人/跟进状态 | |
| TextBox | 跟进内容 | |
| Button | 添加跟进记录 |
五、使用注意事项
- 密码字段在单元格失去焦点后自动恢复掩码状态
- 主表与跟进表通过
ID字段关联 - 动态控件创建时根据数据类型自动选择:
switch (column.DataType.Name) { case "DateTime": /* 创建DateTimePicker */; case "Decimal": /* 创建NumericUpDown */; default: /* 创建ComboBox */; } - 新增跟进记录后自动刷新DataGridView显示
此方案满足所有需求,实际部署时需根据数据源调整绑定逻辑,并添加数据验证机制确保数据完整性。
748

被折叠的 条评论
为什么被折叠?



