winform formularios form example escala autoscalemode automático automatic ajuste c# winforms user-interface optimization

formularios - autosize winform c#



Vista de árbol lenta en C# (6)

En nuestra aplicación principal de WinForm, tenemos una vista en árbol cargada en una sola toma:

  • BeginUpdate ()
  • Carga 20,000 nodos
  • EndUpdate ()

y hasta ahora, el rendimiento sigue siendo bueno. En realidad, es uno de los pocos componentes que no reemplazamos con los de terceros.

El rendimiento de TreeView, en mi experiencia, se vuelve lento cuando carga nodos (de una sola vez, o bajo demanda) sin llamar a Begin / EndUpdate (), especialmente si sus nodos están ordenados, pero si llama a Begin / EndUpdate () correctamente, usted realmente no debería tener problemas de rendimiento relacionados con el componente en sí.

Tengo una aplicación heredada que está escrita en C # y muestra una vista de árbol muy compleja con 10 a 20 mil elementos.

En el pasado, encontré un problema similar (pero en C ++) que resolví con la capacidad OWNERDATA ofrecida por la API de Win32.

¿Hay un mecanismo similar en C #?

EDITAR: El plan es optimizar el tiempo de creación, así como el tiempo de navegación. El método disponible a través de la API Win32 es excelente en ambos casos, ya que reduce el tiempo de inicialización a nada y el número de solicitudes de elementos se limita a solo las visibles en cualquier momento. Joshl: En realidad estamos haciendo exactamente lo que sugiere, pero aún necesitamos más eficiencia.


Para datos grandes en la programación de Windows C #, ya sea en WPF o WinForms, tradicionalmente he añadido nodos de forma dinámica. Cardo la raíz del árbol inicial + hijos + nietos en profundidad. Cuando se expande cualquier nodo, cargo los nodos de árbol que representarían a los nietos del nodo en expansión, si hay alguno.

Este patrón también funciona bien con la recuperación de datos. Si realmente está cargando datos de una fuente de miles o millones de registros, probablemente no quiera cargarlos por adelantado. Ningún usuario quiere esperar a que se cargue, y no hay razón para cargar datos que quizás nunca se visualicen.

Por lo general, cargué los datos del nodo nietos o bisnietos según sea necesario en un hilo de fondo, luego marcalé esos datos al hilo de la interfaz de usuario y creé y agregué los nodos. Esto deja la IU receptiva. Puede decorar visualmente nodos de árbol para indicar que aún se están cargando para el caso en que un usuario se adelanta a su IO en el almacén de datos.


Una técnica para mejorar el rendimiento es cargar TreeNodes a medida que el usuario amplía la vista de árbol. Normalmente, un usuario no requerirá que 20,000 nodos se abran en su pantalla a la vez. Solo cargue el nivel que el usuario necesita ver, junto con la información necesaria para que muestre las posibilidades de uso al usuario (expanda el ícono si existen, cuenta, iconos, etc.). A medida que el usuario expande los nodos, cargue los niños justo a tiempo.

Sugerencia útil de Keith: con los winforms TreeView necesitas tener al menos un nodo hijo o no mostrará el expand [+], pero luego manejarás el evento TreeNodeExpanded para eliminar ese nodo ficticio y poblar los hijos.


NOTA: Esta respuesta queda invalidada por una edición realizada por el autor de la pregunta que dice que ya hace este tipo de cosas, pero decidí publicarla para futura referencia por otros que busquen en este tema.

Cuando he hecho cosas similares en el pasado, he tendido a optar por el estilo ingenuo de carga lenta.

  • Use la propiedad TreeNode.Tag para contener una referencia que puede usar para buscar a los niños
  • Utilice el evento TreeView.BeforeExpand para llenar los nodos secundarios
  • Opcionalmente, use el evento TreeView.AfterCollapse para eliminarlos.
  • Para que aparezcan los recuadros [+] / [-], la mejor manera que he encontrado es crear un TreeNode ficticio singleton que se agregue como un elemento secundario a todos los Nodos despoblados, y verifique su existencia antes de BeforeExpand con BeforeExpand .

Hay una forma de hacer que TreeView funcione mucho mejor y es crear todos los nodos secundarios y conectarlos y luego agregar los nodos a TreeView. Si es el rendimiento gráfico del que estamos hablando.

TreeView tree = new TreeView(); TreeNode root = new TreeNode("Root"); PopulateRootNode(root); // Get all your data tree.Nodes.Add(root);

De lo contrario, cárguelos nodo por nodo usando OnTreeNodeExpanded .


No creo que .NET TreeView sea compatible con lo que desee, aunque este tipo de modelo es compatible con DataGridView de .NET (vea la propiedad VirtualMode de DataGridView). TreeView te permitirá dibujar tus propios nodos pero no te permitirá poblarlos desde alguna tienda virtual.

Si es posible, quizás desee considerar el uso de un DataGridView para su aplicación. De lo contrario, administrar los nodos manualmente (como las menciones de joshl anteriores) podría funcionar si puede solucionar algunos problemas al actualizar la pantalla correctamente cuando se expanden los nodos. Fuera de eso, es posible que desee verificar algunos de los proveedores de terceros, como este (DiveLands SandGrid) , que podría (con énfasis en el poder) apoyar el modo de operación deseado.

NOTA: SandGrid no es admitido por los fondos a partir de finales de julio de 2013.