我创建了一个C#Windows Forms应用程序,我试图尽可能简单地演示我遇到的问题。我正在尝试使用DataGridView允许用户在一列中输入,同时从后台线程获取另一列中的更新。
问题是输入列实际上是不可编辑的,因为 - 我认为 - 用于输出列的更新会导致输入列在用户尝试更改时使用其当前值进行更新
这是DataGridView中的错误吗?有没有更好的方法来做这种事情?任何人都可以推荐一个好的解决方法吗?
以下代码演示了此问题。 “输出”列将不断更新,“输入”列几乎不可编辑。我已将设计器代码(Form1.designer.cs)和Main(来自Program.cs)合并到表单代码(Form1.cs)中 - 因此以下代码应该自行运行。
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Timers;
public partial class Form1 : Form
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGridView = new System.Windows.Forms.DataGridView();
((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
this.SuspendLayout();
//
// dataGridView
//
this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView.Location = new System.Drawing.Point(3, 12);
this.dataGridView.Name = "dataGridView";
this.dataGridView.RowTemplate.Height = 24;
this.dataGridView.Size = new System.Drawing.Size(322, 158);
this.dataGridView.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(328, 174);
this.Controls.Add(this.dataGridView);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView;
public Form1()
{
InitializeComponent();
}
BindingSource bindingSource = new BindingSource();
BindingList<Item> items = new BindingList<Item>();
private System.Timers.Timer timer;
private void Form1_Load(object sender, EventArgs e)
{
dataGridView.DataSource = bindingSource;
bindingSource.DataSource = items;
items.Add(new Item(dataGridView));
timer = new System.Timers.Timer {Interval = 50};
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
private Random random = new Random();
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
items[0].SetOutput(random.Next(100));
}
}
class Item : INotifyPropertyChanged
{
public int Input { get; set; }
private int output;
public int Output
{
get { return output; }
private set
{
output = value;
OnPropertyChanged("Output");
}
}
public Control control;
public Item(Control control)
{
this.control = control;
}
public void SetOutput(int outputValue)
{
Output = outputValue;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
if(!control.IsDisposed)
control.BeginInvoke(handler, this, new PropertyChangedEventArgs(name));
}
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
答案 0 :(得分:1)
我怀疑当PropertyChanged
事件发生时,DataGridView
会刷新所有单元格,或者只更新行中已更改的单元格(当您编辑另一行时是否会发生这种情况?)所有未经修改的变化。
如果您可以在DataGridView
刷新单元格之前拦截事件,则可以保存未提交的更改以在刷新后恢复它们。但那将是一个丑陋的解决方法......
你有没有在MSDN论坛上提问?也许MS的某个人可以给你一个更有用的答案
答案 1 :(得分:0)
正在编辑的细胞可能正在失去焦点?也许每次更新另一列时,存储您编辑的位置,并在更新后重置焦点?
答案 2 :(得分:0)
尝试更新列不是50毫秒,而是像intervale那样等于4000 它的工作对我来说,我可以改变另一列中的值,但仍然可以在另一列中进行更改