2011-10-10 15 views
5

Quiero validar una celda de Winform datagridview con CellValidating. Si el usuario no configuró correctamente un valor, configuré ErrorText y uso e.Cancel, de modo que el cursor permanezca en la celda. El problema ahora es que el error-symbol (y el mensaje de error) no se muestra (en la celda). Cuando elimino e.Cancelar, la celda pierde el foco y se muestra el símbolo de error. ¿Cómo puedo lograr que la celda permanezca en modo de edición y también se muestre el símbolo de error?Winforms: Problemas al validar una celda en una vista de cuadrícula de datos

if (...) 
{ 
    this.datagridviewX.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Errortext"; 
    e.Cancel = true; 
} 
else 
{ 
    this.datagridviewX.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = ""; 
} 
+0

Como digo en mi respuesta, lo que describes no es el comportamiento fuera de la caja, entonces debes estar haciendo algo inusual. ¿Podría proporcionar algún código? –

Respuesta

9

El comportamiento que está viendo es en realidad debido a un problema de pintura y no debido a que el icono de error no se muestre. Lo que sucede es que cuando configuras el texto de error de la celda, se muestra el ícono, pero el cuadro de texto de la celda en el modo de edición está pintado sobre el ícono, por lo tanto, ¡no se muestra ningún ícono al usuario!

usted tiene dos opciones para la fijación del mismo - una es utilizar simplemente el texto de error de la fila así que en vez de:

this.datagridviewX.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Errortext"; 
e.Cancel = true; 

tiene:

this.datagridviewX.Rows[e.RowIndex].ErrorText = "Errortext"; 
e.Cancel = true; 

La otra opción es cambiar la célula relleno de la celda (moviendo el control de edición) y pintando el ícono.

De hecho, encontré esta técnica para resolver el problema here y reproduzco d su código a continuación (en C# y no en VB.Net).

En primer lugar usted tiene su celular validar evento en el que se agrega algo de código para cambiar el relleno de celda:

void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) 
{ 
    if (string.IsNullOrEmpty(e.FormattedValue.ToString())) 
    { 
     DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]; 

     cell.ErrorText = 
      "Company Name must not be empty"; 

     if (cell.Tag == null) 
     { 
      cell.Tag = cell.Style.Padding; 
      cell.Style.Padding = new Padding(0, 0, 18, 0); 
     } 
     e.Cancel = true; 

    } 
    else 
    { 
     dataGridView1.Rows[e.RowIndex].ErrorText = string.Empty; 
    } 
} 

Eso permite que el icono que se ve no es el control de edición se ha movido, excepto el icono se ha trasladado también! Entonces también tenemos que pintar un ícono nuevo.

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) 
{ 
    if (dataGridView1.IsCurrentCellDirty) 
    { 
     if (!string.IsNullOrEmpty(e.ErrorText)) 
     { 
      GraphicsContainer container = e.Graphics.BeginContainer(); 
      e.Graphics.TranslateTransform(18,0); 
      e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon); 
      e.Graphics.EndContainer(container); 
      e.Handled = true; 
     } 
    } 
} 

Luego, cuando se termina la edición en la celda que tenga que restablecer el relleno:

void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) 
{ 
    if (!string.IsNullOrEmpty(dataGridView1[e.ColumnIndex, e.RowIndex].ErrorText)) 
    { 
     DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]; 
     cell.ErrorText = string.Empty; 
     cell.Style.Padding = (Padding)cell.Tag; 
     cell.Tag = null; 
    } 
} 

El puesto donde me encontré con este se niega a establecer el puntero del ratón sobre el nuevo icono pintado - Aquí es un poco de código difícil que aborda eso, no tengo tiempo para hacerlo funcionar de verdad, así que hay algunos pequeños dulces que el pensamiento podría solucionar; lo arreglaré si recibo un minuto más tarde.

Configuro DataGridView.ShowCellToolTips = true e introduzco un booleano enError para rastrear si actualmente tenemos un error de edición. entonces controlar el evento MouseHover:

void dataGridView1_MouseHover(object sender, EventArgs e) 
{ 
    if (inError) 
    {     
     Point pos = this.PointToClient(Cursor.Position);    

     if (r.Contains(pos.X - 20, pos.Y - 5)) 
     {     
      t.Show("There was an error", dataGridView1.EditingControl, 3000); 
     } 
    } 
} 

El t en que el código es un control ToolTip nivel de formulario, y R es un rectángulo.

que pueblan R como a continuación en el controlador de la pintura celular:

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) 
{ 
    if (dataGridView1.IsCurrentCellDirty) 
    { 
     if (!string.IsNullOrEmpty(e.ErrorText)) 
     {    
      GraphicsContainer container = e.Graphics.BeginContainer(); 

      r = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true); 
      e.Graphics.TranslateTransform(18, 0); 
      e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon); 
      e.Graphics.EndContainer(container);    

      e.Handled = true; 
     } 
    } 
} 

No estoy feliz por el menos 20 y menos 5 en la posición de punto - que es lo que me gustaría arreglar si tuviera un poco más de tiempo.

+0

Intenté exactamente esto con dataGridView1.Rows [e.RowIndex] .Cells [e.ColumnIndex] .ErrorText = ... – Kottan

+0

@Kottan proporciona algún código (probablemente sea mejor para todo el formulario si no es demasiado grande) y podemos tener un Mira. –

+0

@Kottan - ok, te tengo ahora. Su pregunta no dejó en claro que estaba configurando el error en la celda y no en la fila. Proporcionar código siempre es algo bueno que hacer. –

Cuestiones relacionadas