2009-07-22 42 views
10

El estándar WPF tree view no admite selecciones múltiples.WPF TreeView con selección múltiple

¿Cómo puedo agregar una vista de árbol que admita selección múltiple a mi aplicación WPF? Los productos comerciales están muy bien (estoy actualmente enterado de una implementación comercial - http://www.telerik.com/products/wpf/treeview.aspx)

+0

Tome un vistazo a esta discusión: http://stackoverflow.com/questions/459375/customizing-the-treeview-to-allow-multi-select/9297158#9297158 –

+0

Compruebe mi respuesta aquí: http://stackoverflow.com/a/13412801/166452 –

Respuesta

1

Dependiendo de la semántica exacta que usted desea, la solución puede ser extremadamente simple:

Si la raíz del árbol es cualquier cosa menos un TreeView - por ejemplo, si se trata de un ItemsControl sin formato, todos los elementos TreeViewItems en el árbol serán seleccionables independientemente, por lo que básicamente obtendrá mulitiselect de forma gratuita. Así que solo use un ItemsControl en lugar de un TreeView para la raíz de su árbol.

Esta solución tiene el beneficio de ser extraordinariamente fácil de implementar. Se diferencia de la solución de mattdlong hecho de que:

  • Su solución elimina la selección de todos los otros elementos cuando se hace clic en un elemento, así que hay que pulsar la tecla Ctrl artículos multiselección.
  • Con esta solución, un solo clic seleccionará/deseleccionará el elemento sobre el que hizo clic, pero no hay forma de seleccionar rápidamente un elemento y simultáneamente anular la selección de todos los demás.

Otra diferencia es que la navegación del teclado (teclas de flecha) en su solución anula la selección de todos los elementos, mientras que en esta solución la navegación por el teclado no anula la selección de elementos.

Debe elegir entre estas soluciones en función de la semántica que prefiera (un solo clic para agregar el elemento vs ctrl-clic para agregar el elemento, etc.). Si desea una semántica más avanzada, como Shift-Click, etc., es relativamente de agregar.

Tenga en cuenta que también puede TreeViewItems estilo personalizado utilizando un ToggleButton o CheckBox en cualquier parte del ItemContainerTemplate que tiene Checked={Binding IsSelected}. Esto permite al usuario seleccionar elementos haciendo clic en ToggleButton o CheckBox.

+1

Tengo alguna experiencia con los árboles en la interfaz de usuario para aprender una regla: hay tantos detalles en la implementación de la selección múltiple correctamente, que realmente no deseo toma este camino. Prefiero a alguien, cuyo negocio es el diseño de controles de interfaz de usuario y que ya ha invertido en pruebas y ajuste, en lugar de producir algo rápido, que constantemente atraerá recursos para arreglar y mantener. Es bueno como un ejercicio de programación, concedido. – mark

+0

Creo que malinterpretaste mi respuesta. Lo que intentaba decir es que TreeViewItem es compatible con la multiselección simple de fábrica, por lo que ** no tiene que escribir nada en absoluto. ** Si le gusta la semántica multiselección incorporada, puede usarla. Si desea algo diferente al comportamiento integrado de selección múltiple **, entonces ** tendrá que comprar un código de control o de escritura como mattdlong describe. –

+2

Cuando trato de reemplazar un control TreeView con un ItemsControl, todo falla con un seguimiento de la pila más largo que una página. Un estilo para TreeViewItem no se puede aplicar a ese control, o algo. Entonces, ¿cómo se supone que funciona? ¿Sigue siendo un control de árbol jerárquico o se convertirá en una lista plana entonces? (En cuyo caso sería inútil.) – ygoe

12

El siguiente código funciona bien y es mucho más simple. Sin embargo, el inconveniente es el uso de la propiedad no pública, IsSelectionChangeActive, de la clase treeview. Código de abajo:

private static readonly PropertyInfo IsSelectionChangeActiveProperty 
    = typeof (TreeView).GetProperty 
    (
     "IsSelectionChangeActive", 
     BindingFlags.NonPublic | BindingFlags.Instance 
    ); 

public static void AllowMultiSelection(TreeView treeView) 
{ 
    if (IsSelectionChangeActiveProperty==null) return; 

    var selectedItems = new List<TreeViewItem>(); 
    treeView.SelectedItemChanged += (a, b) => 
    { 
    var treeViewItem = treeView.SelectedItem as TreeViewItem; 
    if (treeViewItem == null) return; 

    // allow multiple selection 
    // when control key is pressed 
    if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) 
    { 
     // suppress selection change notification 
     // select all selected items 
     // then restore selection change notifications 
     var isSelectionChangeActive = 
     IsSelectionChangeActiveProperty.GetValue(treeView, null); 

     IsSelectionChangeActiveProperty.SetValue(treeView, true, null); 
     selectedItems.ForEach(item => item.IsSelected = true); 

     IsSelectionChangeActiveProperty.SetValue 
     (
     treeView, 
     isSelectionChangeActive, 
     null 
    ); 
    } 
    else 
    { 
     // deselect all selected items except the current one 
     selectedItems.ForEach(item => item.IsSelected = (item == treeViewItem)); 
     selectedItems.Clear(); 
    } 

    if (!selectedItems.Contains(treeViewItem)) 
    { 
     selectedItems.Add(treeViewItem); 
    } 
    else 
    { 
     // deselect if already selected 
     treeViewItem.IsSelected = false; 
     selectedItems.Remove(treeViewItem); 
    } 
    }; 

} 
+1

¡Agradable! Un método que funciona, utiliza el TreeView existente (es decir, no lo reescribe desde cero) y utiliza la propia propiedad de dependencia IsSelected de TreeView. Tuve que cambiar TreeViewItem al elemento que había establecido el enlace, pero eso fue todo. Gracias. – markmuetz

+0

Tiene algunos problemas. Una de ellas es que no puedes Ctrl + seleccionar y Ctrl + anular la selección del mismo elemento. Supongo que es porque no se activa ningún evento SelectedItemChanged al hacer clic en el mismo elemento dos veces. Estoy investigando. Y una pregunta abierta es cómo puedo usar el enlace de datos para SelectedItem con múltiples selecciones. – ygoe

+0

¿Alguna vez lograste arreglar Ctrl + seleccionar y Ctrl + deseleccionar error? – user589195