Hola,
El problema es el siguiente: inserto filas en un datagridview y cuando llega a un determinado número de filas se queda la app congelada y el scroll vertical no aparece si no que hace algo raro. Además tengo la propiedad ScrollBar en Vertical.
Personalmente no sé que puede estar pasando quizas un problema de la interfaz .... ni idea. He estado buscando por internet y a la gente este componente no suele darle muchos problemas.
¿Se os ocurre que puede estar pasando?
#########################
Ya aparece el scroll era simplemente que tenia la propiedad AutoSize = true; y claro había que ponerla a false. Pero el problema sigue existiendo cuando aparece el scroollBar la app se queda congelada.
Si estás utilizando el método DataGridView.Rows.Add que toma cómo argumento el número de filas a crear, entonces el thread de la UI no se podrá actualizar hasta que finalice dicha operación de inserción de filas, por ende, la UI se congelará.
Habría que ver el código para poder comprobar el qué y cómo lo estás haciendo, ya que quizás haya otros problemas que estén derivando en esa congelación del thread, así que si no das más datos no se te puede ayudar a buscar la solución más eficiente para el problema que sea en cuestión.
De todas formas, puedes añadir las filas de manera asíncrona para solventar el problema de congelación, pero esto tomará bastante más tiempo en añadir todas las filas:
Public Class Form1
Private WithEvents bgw As New BackgroundWorker
Private Sub Button1_Click(sender As Object, e As EventArgs) _
Handles Button1.Click
DataGridView1.ColumnCount = 1
bgw.RunWorkerAsync()
End Sub
Sub DoRowAdd(ByVal dgv As DataGridView, ByVal row As DataGridViewRow)
If dgv.InvokeRequired Then
dgv.Invoke(Sub() dgv.Rows.Add(row))
Else
dgv.Rows.Add(row)
End If
End Sub
Sub Work(ByVal sender As Object, ByVal e As EventArgs) _
Handles bgw.DoWork
For rowIndex As Integer = 0 To Short.MaxValue
Dim row As New DataGridViewRow
row.Cells.Add(New DataGridViewTextBoxCell With {.Value = rowIndex})
Me.DoRowAdd(Me.DataGridView1, row)
Next rowIndex
End Sub
End Class
Otra alternativa sería añadir las filas una a una cómo en el ejemplo anterior, pero utilizando el método Application.DoEvents para que tras cada inserción se procese el resto de mensajes (eventos) en cola para actualizar la UI;
el tiempo que se toma en crear las filas es practicamente el mismo que en el ejemplo de arriba.
DataGridView1.Columns.Add(String.Empty, String.Empty)
For rowIndex As Integer = 0 To Short.MaxValue
DataGridView1.Rows.Add({rowIndex})
Application.DoEvents()
Next rowIndex
También lo que puedes hacer al utilizar el método DataGridView.Rows.Add que toma cómo argumento el número de filas a crear, es suspender la lógica del layout del control, esto aceleraría bastante el tiempo que tarda en agregar todas las filas, pero obviamente no se desbloquearía la UI.
DataGridView1.Columns.Add(String.Empty, String.Empty)
DataGridView1.SuspendLayout()
DataGridView1.Rows.Add(Short.MaxValue)
DataGridView1.ResumeLayout()
EDITO: Ups, perdón, no me di cuenta que lo preguntaste en C#, aquí tienes una conversión online:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class Form1
{
private BackgroundWorker withEventsField_bgw = new BackgroundWorker();
private BackgroundWorker bgw {
get { return withEventsField_bgw; }
set {
if (withEventsField_bgw != null) {
withEventsField_bgw.DoWork -= Work;
}
withEventsField_bgw = value;
if (withEventsField_bgw != null) {
withEventsField_bgw.DoWork += Work;
}
}
}
private void Button1_Click(object sender, EventArgs e)
{
DataGridView1.ColumnCount = 1;
bgw.RunWorkerAsync();
}
public void DoRowAdd(DataGridView dgv, DataGridViewRow row)
{
if (dgv.InvokeRequired) {
dgv.Invoke(() => dgv.Rows.Add(row));
} else {
dgv.Rows.Add(row);
}
}
public void Work(object sender, EventArgs e)
{
for (int rowIndex = 0; rowIndex <= short.MaxValue; rowIndex++) {
DataGridViewRow row = new DataGridViewRow();
row.Cells.Add(new DataGridViewTextBoxCell { Value = rowIndex });
this.DoRowAdd(this.DataGridView1, row);
}
}
}
//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================
Considero que los otros dos ejemplos no necesitan una conversión a C# para entenderlos.
Saludos!
muchismas gracias Electro voy a probarlo a ver si eso me puede solucionar el problema. Además haciendo pruebas he visto que es cuando inserto fila con "DataGridView.Rows.Add" y se completa el datagrid ocurre esto. Creo que es tema del sincronismo voy a probarlo y os comento.
saludos.
Hola de nuevo,
Sinceramente no sé por que ocurre esto: Cuando intento visualizar mas elementos que el tamaño del datagridView no aparece la barra vertical y además la app se queda bloqueada. Estoy implementando tu código adaptandolo pero me da un error diciendo que no se puede convertir una expresión lambda en un System.Delegate. Entiendo lo que me quiere decir pero no se me ocurre como implementarlo.
por ejemplo así: Teniendo un delegado que llame a mi método.
private void updateVisualizacionMatricula(String texto)
{
if (this.InvokeRequired)
{
updateVisualizacionMatricula_ d = new updateVisualizacionMatricula_(updateVisualizacionMatricula);
this.Invoke(d, new object[] { texto });
}
else
{
lb_visualizacionMatricula.Text = texto;
int x = groupBoxVisualizacion.Width + label29.Width;
int w = lb_visualizacionMatricula.Width;
lb_visualizacionMatricula.Left = x / 2 - w / 2;
}
}
A y otra cosa ¿Cómo podría pasar los distintos parámetros al método InsertarFila en el método work?
public void InsertarFilaDescarga(String modelo,
String calidad,
String color,
String talla,
String TotalTeorica,
String TotalReal,
String lote)
{
//Creamos fila;
DataGridViewRow row = new DataGridViewRow();
DataGridViewButtonColumn buttonColumn = new DataGridViewButtonColumn();
buttonColumn.UseColumnTextForButtonValue = true;
row.Cells.Add(new DataGridViewTextBoxCell { Value = modelo });
row.Cells.Add(new DataGridViewTextBoxCell { Value = calidad});
row.Cells.Add(new DataGridViewTextBoxCell { Value = color });
row.Cells.Add(new DataGridViewTextBoxCell { Value = talla });
if (lote.Equals("x1"))
{
row.Cells.Add(new DataGridViewButtonCell { Value = "x1" });
}
else if (lote.Equals("x2"))
{
row.Cells.Add(new DataGridViewButtonCell { Value = "x2" });
}
else
{
row.Cells.Add(new DataGridViewTextBoxCell { Value = "" });
//dGV_Descarga.Rows.Add(new object[] { modelo, calidad, color, talla,
// null,TotalTeorica,TotalReal});
//var cell = dGV_Descarga.Rows[dGV_Descarga.RowCount - 1].Cells[4] = new DataGridViewTextBoxCell();
//cell.Value = "";
//cell.ReadOnly = true;
}
row.Cells.Add(new DataGridViewTextBoxCell { Value = TotalTeorica });
row.Cells.Add(new DataGridViewTextBoxCell { Value = TotalReal });
//insertamos fila
if (dGV_Descarga.InvokeRequired)
{
dGV_Descarga.Invoke(() => dGV_Descarga.Rows.Add(row));
}
else
{
dGV_Descarga.Rows.Add(row);
}
}
public void InsertarFilaDescarga(DataGridView dg , DataGridViewRow row)
{
if (dg.InvokeRequired)
{
dg.Invoke(() => dg.Rows.Add(row));
}
else
{
dg.Rows.Add(row);
}
}
al final lo conseguí mañana lo comentaré y pondré el código.
Mi manejo en C# no es muy bueno.
Puedes declarar el delegado:
internal delegate void UpdateVisualizacionMatriculaDelegate(string texto);
private void updateVisualizacionMatricula()
{
if (this.InvokeRequired) {
this.Invoke(new UpdateVisualizacionMatriculaDelegate(updateVisualizacionMatricula), texto);
} else {
lb_visualizacionMatricula.Text = texto;
int x = groupBoxVisualizacion.Width + label29.Width;
int w = lb_visualizacionMatricula.Width;
lb_visualizacionMatricula.Left = x / 2 - w / 2;
}
}
//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================
O también puedes usar el delegado Action para evitar la declaración de delegados adicionales en el código
this.Invoke(new Action<string>(updateVisualizacionMatricula), texto)