Cada vez que se selecciona un nodo en mi vista de árbol, automáticamente se desplaza horizontalmente a ese elemento. ¿Hay alguna forma de desactivar esto?Prevenir el desplazamiento horizontal automático en TreeView
Respuesta
Gestione el evento RequestBringIntoView y establezca Handled en true, y la infraestructura no intentará mostrar el elemento. Por ejemplo, hacer algo como esto en su XAML:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<EventSetter Event="RequestBringIntoView" Handler="TreeViewItem_RequestBringIntoView"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Y luego esto en su código subyacente:
private void TreeViewItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
e.Handled = true;
}
logré resolver el problema utilizando la siguiente:
<TreeView ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=1}}" />
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
</TreeView>
Ato el ancho del StackPanel que representa el Panel de elementos aquí, al Anchura real de ContentPresenter en el TreeView.
También funciona bien con el "hackeado" Stretching TreeView por: http://blogs.msdn.com/b/jpricket/archive/2008/08/05/wpf-a-stretching-treeview.aspx (modifiqué esa solución para no eliminar la columna de cuadrícula, sino para cambiar la propiedad Grid.Column del primer elemento Decorator de 1 a 2).
¡Impresionante! ¡Gracias! – John
Matthew, gestioné para conservar el desplazamiento vertical, y solo evité el desplazamiento horizontal restaurando la posición horizontal después de un desplazamiento causado por el evento RequestBringIntoView.
private double treeViewHorizScrollPos = 0.0;
private bool treeViewResetHorizScroll = false;
private ScrollViewer treeViewScrollViewer = null;
private void TreeViewItemRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
if (this.treeViewScrollViewer == null)
{
this.treeViewScrollViewer = this.DetailsTree.Template.FindName("_tv_scrollviewer_", this.DetailsTree) as ScrollViewer;
if(this.treeViewScrollViewer != null)
this.treeViewScrollViewer.ScrollChanged += new ScrollChangedEventHandler(this.TreeViewScrollViewerScrollChanged);
}
this.treeViewResetHorizScroll = true;
this.treeViewHorizScrollPos = this.treeViewScrollViewer.HorizontalOffset;
}
private void TreeViewScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (this.treeViewResetHorizScroll)
this.treeViewScrollViewer.ScrollToHorizontalOffset(this.treeViewHorizScrollPos);
this.treeViewResetHorizScroll = false;
}
Impresionante. usando e.Handled = verdadero; no funcionó para mí, ¡pero tuyo definitivamente lo hace! – mdiehl13
que tenían una cuadrícula de datos que lo que quería hacer la misma operación y se utiliza en la respuesta de POHB en su mayoría. Tuve que modificarlo para mi solución. El código se muestra a continuación. La cuadrícula de datos es una cuadrícula de datos de 2 x 2 con la primera columna delgada y la segunda muy amplia (1000+). La primera columna está congelada. Espero que ésto ayude a alguien. -Matt
public partial class MyUserControl : UserControl
{
private ScrollContentPresenter _scrollContentPresenter;
private ScrollViewer _scrollViewer;
private double _dataGridHorizScrollPos = 0.0;
private bool _dataGridResetHorizScroll = false;
public MyUserControl()
{
// setup code...
_dataGrid.ApplyTemplate();
_scrollViewer = FindVisualChild<ScrollViewer>(_dataGrid);
_scrollViewer.ScrollChanged += new ScrollChangedEventHandler(DataGridScrollViewerScrollChanged);
_scrollContentPresenter = FindVisualChild<ScrollContentPresenter>(_scrollViewer);
_scrollContentPresenter.RequestBringIntoView += new RequestBringIntoViewEventHandler(_scrollContentPresenter_RequestBringInputView);
}
private void DataGridScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (_dataGridResetHorizScroll)
{
_scrollViewer.ScrollToHorizontalOffset(_dataGridHorizScrollPos);
}
// Note: When the row just before a page change is selected and then the next row on the
// next page is selected, a second event fires setting the horizontal offset to 0
// I'm ignoring those large changes by only recording the offset when it's large. -MRB
else if (Math.Abs(e.HorizontalChange) < 100)
{
_dataGridHorizScrollPos = _scrollViewer.HorizontalOffset;
}
_dataGridResetHorizScroll = false;
}
public T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if ((child != null) && (child is ScrollViewer))
{
// I needed this since the template wasn't applied yet when
// calling from the constructor
(child as ScrollViewer).ApplyTemplate();
}
if (child != null && child is T)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null) return childItem;
}
}
return null;
}
private void _scrollContentPresenter_RequestBringInputView(object sender, RequestBringIntoViewEventArgs e)
{
_dataGridResetHorizScroll = true;
}
Tuve un problema similar. Necesitaba evitar el desplazamiento horizontal, pero conservaba el desplazamiento vertical. Mi solución es manejar el método OnRequestBringIntoView
ya que quiero que se comporte. Creé un ResourceDictionary
para un TreeViewItem
y agregué EventSetters
para los métodos OnSelected
y OnRequestBringIntoView
.
MyResourceDictionary.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="Resources.MyResourceDictionary" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TreeViewItem" x:Key="treeitem" >
<EventSetter Event="RequestBringIntoView" Handler="OnRequestBringIntoView"/>
<EventSetter Event="Selected" Handler="OnSelected"/>
</Style>
</ResourceDictionary>
MyResourceDictionary.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Resources
{
partial class MyResourceDictionary:ResourceDictionary
{
public MyResourceDictionary()
{
InitializeComponent();
}
private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
e.Handled = true; //prevent event bubbling
var item = (TreeViewItem)sender;
TreeView tree = GetParentTree(item) as TreeView;
if(tree!=null)
{
var scrollViewer = tree.Template.FindName("_tv_scrollviewer_", tree) as ScrollViewer;
if (scrollViewer != null)
{
scrollViewer.ScrollToLeftEnd();//prevent horizontal scroll
Point relativePoint = item.TransformToAncestor(tree).Transform(new Point(0, 0));//get position of a selected item
if (relativePoint.Y <= scrollViewer.ContentVerticalOffset) return;//do no scroll if we select inside one 'scroll screen'
scrollViewer.ScrollToVerticalOffset(relativePoint.Y);//scroll to Y of a selected item
}
}
}
private DependencyObject GetParentTree(DependencyObject item)
{
var target = VisualTreeHelper.GetParent(item);
return target as TreeView != null ? target : GetParentTree(target);
}
private void OnSelected(object sender, RoutedEventArgs e) //handle programmatically selected items
{
var item = (TreeViewItem)sender;
item.BringIntoView();
e.Handled = true;
}
}
}
@ solución de lena de preservar desplazamiento vertical funcionado mejor para mí. He iterado en él un poco:
private void TreeViewItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
var treeViewItem = (TreeViewItem)sender;
var scrollViewer = treeView.Template.FindName("_tv_scrollviewer_", treeView) as ScrollViewer;
Point topLeftInTreeViewCoordinates = treeViewItem.TransformToAncestor(treeView).Transform(new Point(0, 0));
var treeViewItemTop = topLeftInTreeViewCoordinates.Y;
if (treeViewItemTop < 0
|| treeViewItemTop + treeViewItem.ActualHeight > scrollViewer.ViewportHeight
|| treeViewItem.ActualHeight > scrollViewer.ViewportHeight)
{
// if the item is not visible or too "tall", don't do anything; let them scroll it into view
return;
}
// if the item is already fully within the viewport vertically, disallow horizontal scrolling
e.Handled = true;
}
Lo que esto hace es dejar que el desplazamiento ScrollViewer normalmente si el artículo no está ya en la vista vertical. Sin embargo, para el caso "molesto" real (donde el elemento ya está visible), establece e.Handled en verdadero, lo que impide el desplazamiento horizontal.
para ofrecer una versión ligeramente simplificada de respuesta @ lena:
Para desplazarse verticalmente preservando al mismo tiempo la posición de desplazamiento horizontal, y sin efectos secundarios no deseados, en el XAML, agregar controladores de eventos para RequestBringIntoView y seleccionados:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="RequestBringIntoView" Handler="TreeViewItem_RequestBringIntoView"/>
<EventSetter Event="Selected" Handler="OnSelected"/>
...
En el código subyacente, agregue dos controladores de eventos:
private void TreeViewItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
// Ignore re-entrant calls
if (mSuppressRequestBringIntoView)
return;
// Cancel the current scroll attempt
e.Handled = true;
// Call BringIntoView using a rectangle that extends into "negative space" to the left of our
// actual control. This allows the vertical scrolling behaviour to operate without adversely
// affecting the current horizontal scroll position.
mSuppressRequestBringIntoView = true;
TreeViewItem tvi = sender as TreeViewItem;
if (tvi != null)
{
Rect newTargetRect = new Rect(-1000, 0, tvi.ActualWidth + 1000, tvi.ActualHeight);
tvi.BringIntoView(newTargetRect);
}
mSuppressRequestBringIntoView = false;
}
private bool mSuppressRequestBringIntoView;
// Correctly handle programmatically selected items
private void OnSelected(object sender, RoutedEventArgs e)
{
((TreeViewItem)sender).BringIntoView();
e.Handled = true;
}
- 1. C# WinForms TreeView eliminar barra de desplazamiento horizontal
- 2. Desplazamiento horizontal?
- 3. Vista de desplazamiento horizontal en páginas de desplazamiento horizontal
- 4. ¿Cómo obtener un TextView en Android tiene desplazamiento horizontal y desplazamiento automático?
- 5. detener el desplazamiento horizontal en JTextArea
- 6. ¿Cómo detectar el desplazamiento horizontal en jQuery?
- 7. Deshabilitar el desplazamiento automático RichTextBox
- 8. QGraphicsView: Deshabilitar el desplazamiento automático
- 9. desplazamiento automático suave utilizando javascript
- 10. touchpad desplazamiento horizontal en emacs
- 11. deshabilitar desplazamiento horizontal en jscrollpane
- 12. Desplazamiento horizontal infinito UIScrollView
- 13. UIScrollView no desplazamiento horizontal
- 14. Posición fija - Desplazamiento horizontal
- 15. Habilitar desplazamiento para WPF Treeview
- 16. desplazamiento horizontal CSS
- 17. Desplazamiento horizontal - Móvil - ¿deslizar?
- 18. ¿Cómo implementar el desplazamiento automático en DataGridView?
- 19. PhoneGap/Cordova: evitar el desplazamiento horizontal
- 20. Cómo deshabilitar el desplazamiento horizontal de UIWebview?
- 21. Cómo prevenir el escape automático de caracteres especiales en Python
- 22. ¿Cómo prevenir el cierre automático de las llaves en ReSharper?
- 23. iPhone Mesa de desplazamiento horizontal
- 24. CSS problema de desplazamiento horizontal
- 25. desplazamiento horizontal con desbordamiento-x
- 26. div desplazamiento horizontal usando botones
- 27. div con desplazamiento horizontal solo
- 28. jqGrid barra de desplazamiento horizontal
- 29. Deshabilitar desplazamiento horizontal con JavaScript
- 30. PDF Ver con desplazamiento horizontal
¿hay alguna manera de preservar desplazamiento vertical, y sólo impiden horiz desplazamiento vertical –
para @MatthewPirocchi y otros que tienen el mismo problema: parece que encontré una solución http://stackoverflow.com/a/34269542/692829 – lena
Una solución nueva y más simple para permitir el desplazamiento vertical sin cambiar el desplazamiento de desplazamiento horizontal (con no hay efectos secundarios no deseados), vea esta respuesta: http://stackoverflow.com/questions/3225940/prevent-automatic-horizontal-scroll-in-treeview/34269542#42238409 –