visual tutorial studio pagina framework examples application wpf

tutorial - ¿Cómo deseleccionar todos los elementos seleccionados en una vista de árbol de WPF al hacer clic en algún área vacía?



wpf vs winforms (8)

Encontré que esto funciona mucho mejor para mí. Compruebo la fuente original que, si viene de treeviewitem, será una imagen o un bloque de texto. También uso un objeto de vista con una HierarchicalDataTemplate y la BasicTreeViewBase es la clase base para todos mis objetos diferentes. Aquí está el código.

private void TemplateTreeView_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Right && !(e.OriginalSource is Image) && !(e.OriginalSource is TextBlock)) { BasicTreeViewBase item = TemplateTreeView.SelectedItem as BasicTreeViewBase; if (item != null) { TemplateTreeView.Focus(); item.IsSelected = false; } } }

Tengo un problema bastante gracioso con WPF. Tengo una vista en árbol, y la selección de elementos funciona bien hasta el momento. El problema es que quiero deseleccionar el elemento seleccionado actualmente cuando el usuario hace clic dentro del área en blanco de la vista en árbol. De forma predeterminada, la vista en árbol mantiene seleccionado el elemento actual, y he agregado una opción de menú contextual para anular la selección, que es bastante difícil:

// Note: This is done recursivly from the start, so it // works for child items as well treeView.ItemContainerGenerator.ContainerFromItem(treeView.SelectedItem) as TreeViewItem).IsSelected = false;

Además, esto es contra-intuitivo, ya que requiere que el usuario haga clic con el botón derecho en primer lugar, y segundo, luego de anular su selección de esta manera, el usuario ya no puede seleccionarlo haciendo clic en el elemento. ¿Cómo se supone que esto funcione?

Editar: Algo más de información: he agregado un controlador a TreeView para manejar los eventos de clic del mouse, pero el remitente siempre es una instancia de TreeView , incluso si hago clic directamente en TreeViewItem . Si agrego un controlador a mi TreeView.ItemTemplate lugar (es decir, el primer elemento secundario en la plantilla), nunca obtengo eventos cuando hago clic en el área vacía (lo cual es bastante lógico). El código se ve así:

private void MyTreeView_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { if ((sender as TreeViewItem) == null) { // Always triggered System.Diagnostics.Trace.Write("Empty area clicked"); } }

Y el XAML para esto es:

<TreeView x:Name="MyTreeView" Margin="3" MouseUp="MyTreeView_MouseUp">


El problema no seleccionable puede resolverse con una llamada a Focus on the TreeView después de configurar TreeViewItem.IsSelected.


Esto anulará la selección del TreeViewItem seleccionado actualmente si no se hizo clic en ninguno:

private void MyTreeView_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if ((sender as TreeViewItem) == null) { TreeViewItem item = MyTreeView.SelectedItem as TreeViewItem; if(item != null){ item.IsSelected = false; } } }

Espero que esto es lo que estabas buscando!


Implementé un control de selección general una vez y requirió este comportamiento.

Así es como se veía mi método (adaptado para treeview):

protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); DependencyObject dpSource = e.OriginalSource as DependencyObject; if (dpSource.FindVisualAncestor(o => typeof(TreeViewItem).IsAssignableFrom(o.GetType())) == null) UnselectAll(); }

Básicamente, sube el árbol desde la fuente. Si no se encontró un TreeViewItem, el usuario hizo clic en el espacio vacío.


Puede haber dos problemas más:

  1. La vista en árbol está encuadernada, por lo que SelectedItem es un elemento de la colección encuadernada.
  2. Hay muchos niveles para que ItemContainerGenerator no contenga objetos de nivel más profundo

por todo este motivo, uso esta función, pero la selección no debe desencadenar ningún evento.

private void UnselectTreeViewItem(TreeView pTreeView) { if(pTreeView.SelectedItem == null) return; if(pTreeView.SelectedItem is TreeViewItem) { (pTreeView.SelectedItem as TreeViewItem).IsSelected = false; } else { TreeViewItem item = pTreeView.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem; if (item != null) { item.IsSelected = true; item.IsSelected = false; } } }


Use la clase de extensión a continuación

public static class TreeViewExtensions { public static TreeViewItem ContainerFromItem(this TreeView treeView, object item) { TreeViewItem containerThatMightContainItem = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(item); if (containerThatMightContainItem != null) return containerThatMightContainItem; else return ContainerFromItem(treeView.ItemContainerGenerator, treeView.Items, item); } private static TreeViewItem ContainerFromItem(ItemContainerGenerator parentItemContainerGenerator, ItemCollection itemCollection, object item) { foreach (object curChildItem in itemCollection) { TreeViewItem parentContainer = (TreeViewItem)parentItemContainerGenerator.ContainerFromItem(curChildItem); TreeViewItem containerThatMightContainItem = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(item); if (containerThatMightContainItem != null) return containerThatMightContainItem; TreeViewItem recursionResult = ContainerFromItem(parentContainer.ItemContainerGenerator, parentContainer.Items, item); if (recursionResult != null) return recursionResult; } return null; } }

Luego, en el evento MouseDown de treeview, use el método de extensión de la siguiente manera:

private void trview_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if ((sender as TreeViewItem) == null) { if (this.trview.ContainerFromItem(trview.SelectedItem) != null) { this.trview.ContainerFromItem(trview.SelectedItem).IsSelected = false; } } this.trview.Focus(); }

Espero que funcione para ti. Lo tengo trabajando de esta manera ...


Me encontré con esta situación yo mismo con una implementación personalizada de Vista de lista de árbol después de buscar durante mucho tiempo. Finalmente encontré una solución que funcionó para mí.

La explicación completa se puede encontrar en http://social.msdn.microsoft.com/Forums/vstudio/en-US/36aca7f7-0b47-488b-8e16-840b86addfa3/getting-treeviewitem-for-the-selected-item-in -a-treeview

La idea básica es capturar el evento TreeViewItem.Selected y guardar el origen del evento en el atributo Tag en su TreeView. Luego, cuando necesite borrarlo, puede acceder al atributo Tag en su control y establecer el valor IsSelected en False. Esto funciona para mí con 2 niveles de niños anidados. Espero que funcione para usted.

Por el bien de la persistencia:

Declaración TreeView

<TreeView Name="myTreeView" TreeViewItem.Selected="OnItemSelected" ItemsSource="{Binding Source={StaticResource myHierarchicalData}}"/>

Controlador de eventos

private void OnItemSelected(object sender, RoutedEventArgs e) { myTreeView.Tag = e.OriginalSource; }

Borrar la lógica de selección

if (myTreeView.SelectedItem != null) { TreeViewItem selectedTVI = myTreeView.Tag as TreeViewItem; // add your code here mine was selectedTVI.IsSelected = false; }


Para una vista en árbol C #, use treeview.SelectedNode = null; No estoy seguro de si esto funciona para WPF.