【发布时间】:2018-09-01 02:41:39
【问题描述】:
我正在向用户显示一个 DataGridView。此 DataGridView 将其 DataSource 设置为带有标识符(“ID”)的 DataTable,以及其他数据。每次更改 ID 列中的值时,我都想遍历所有行以检查 ID 是否真正唯一;但是,当任何其他列发生更改时,我想避免这样做,因为对 ID 列执行的任务非常繁重。因此,我认为使用 ColumnChanged 事件是一个不错的选择,我可以从中访问已更改的列,并在需要时重置值。
当现有行在长列表中发生更改时,这种方法效果很好,但是,我注意到一个主要缺陷:当我通过 DataGridView 添加新行时,会触发 ColumnChanged 事件,而行本身实际上并未包含在DataTable,因此遍历 DataTable 会缺少一行,导致许多任务无法正确处理 DataTable。
我注意到,一旦调用 RowChanged,DataTable 确实 包含该行,但我无法访问更改了哪一列,正如上面指出的那样,我需要这样做。有没有办法解决这个问题或者我可以使用什么解决方法?
为了形象化我的问题,我做了下面的例子:每次更改 ID 列时,都会通知用户更改,而程序会检查是否有重复的 ID,如果有则通知用户。但是,您会发现,当您添加新行并且在其中做的第一件事是将 ID 列更改为已存在的值时,用户将收到更改通知,但不会通知重复。
(请注意,此示例只是一个示例,我实际检查 DataTable 的方式要复杂得多,因此我要求在调用事件时该行存在于 DataTable 中。)
Program.cs(这是从 Visual Studio 默认生成的):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
static class Program
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.Designer.cs(标准生成的Form类加DataGridView):
namespace WindowsFormsApp2
{
partial class Form1
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(0, 0);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.RowTemplate.Height = 24;
this.dataGridView1.Size = new System.Drawing.Size(800, 450);
this.dataGridView1.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView1;
}
}
Form1.cs(重要的东西):
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
private DataTable dt;
public Form1()
{
InitializeComponent();
dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("First Name");
dt.Columns.Add("Last Name");
DataRow dr = dt.NewRow();
dr["ID"] = "1";
dr["First Name"] = "John";
dr["Last Name"] = "Smith";
dt.Rows.Add(dr);
dataGridView1.DataSource = dt;
dt.ColumnChanged += Dt_ColumnChanged;
}
private void Dt_ColumnChanged(object sender, DataColumnChangeEventArgs e)
{
if (e.Column.ColumnName == "ID")
{
MessageBox.Show("The ID column has been changed, it will now be checked.");
List<string> names = new List<string>();
foreach (DataRow dr in dt.Rows)
{
string id = (string)dr["ID"];
if (names.Contains(id))
{
MessageBox.Show("The ID " + id + " is already present.");
}
else
{
names.Add(id);
}
}
}
}
}
}
【问题讨论】:
-
尝试以下操作:找到布尔值 = dt.AsEnumerable().Any(x => x.Field
("ID") == "abcd"); -
如果我理解正确,这段代码会检查字符串是否已经存在并将其作为布尔值返回。可悲的是,这不太适合我的问题,因为相应的行不会突然出现在 DataTable 中。我提供的示例只是用于可视化问题,我在实际程序中检查 DataTable 的方式要复杂得多,并且需要通过多个文件中的 DataTable 呈现和引用整行。
标签: c# .net winforms datagridview datatable