2009-12-21 12 views
5

He creado una aplicación C# Windows Forms que he intentado hacer lo más simple posible para demostrar un problema que me estoy encontrando. Intento utilizar un DataGridView para permitir la entrada del usuario en una columna y al mismo tiempo obtener actualizaciones en otra columna de una cadena de fondo.DataGridView - Entrada y salida simultáneas - ¿Esto es un error en DataGridView

El problema es que la columna Entrada no se puede editar porque, creo, las actualizaciones destinadas a la columna Salida hacen que la columna Entrada se actualice con su valor actual mientras el usuario intenta cambiar eso.

¿Este es un error en DataGridView? ¿Hay una mejor manera de hacer este tipo de cosas? ¿Alguien puede recomendar una buena solución?

El siguiente código demuestra el problema. La columna Salida se actualizará continuamente y la columna Entrada prácticamente no se puede editar. He fusionado el código de diseñador (Form1.designer.cs) y Main (de Program.cs) en el código de formulario (Form1.cs), por lo que el siguiente código debería funcionar por sí mismo.

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()); 
    } 
} 

Respuesta

1

Sospecho que cuando ocurre un evento PropertyChanged, DataGridView actualiza todas las celdas, o tal vez solo las celdas en la fila que cambió (¿sucede cuando está editando otra fila?), Perdiendo todos los cambios no comprometidos.

Si puede interceptar el evento antes de que DataGridView actualice las celdas, puede guardar los cambios sin compromiso para restaurarlos después de la actualización. Pero eso sería una solución fea ...

¿Ha preguntado en los foros de MSDN? Tal vez alguien de MS podría darle una respuesta más útil

+0

Publiqué la misma pregunta en MSDN siguiendo su comentario aquí. Hasta ahora, en más de una semana, no he tenido respuesta. –

0

¿Tal vez la celda que se está editando está perdiendo el foco? ¿Quizás cada vez que actualice la otra columna, almacene donde estaba editando y restablezca el foco después de la actualización?

+0

La celda que se está editando no parece perder el foco, sin embargo se restablece a su valor anterior cada vez que se actualiza la otra columna (10 veces por segundo en mi ejemplo). Se puede actualizar si escribe un número y regresa MUY rápido. –

0

intente actualizar la columna no en 50 milisegundos, pero en algo como intervalo igual a 4000 su trabajo para mí podría cambiar el valor en la otra columna y seguir obteniendo cambios en la otra columna