Chaque fois qu'un nœud est sélectionné dans ma vue arborescente, il fait automatiquement défiler horizontalement vers cet élément. Y at-il un moyen de désactiver cela?Empêcher le défilement horizontal automatique dans TreeView
Répondre
Gérez l'événement RequestBringIntoView et définissez Handled sur true, et l'infrastructure n'essaiera pas d'afficher l'élément. Par exemple, faire quelque chose comme ceci dans votre XAML:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<EventSetter Event="RequestBringIntoView" Handler="TreeViewItem_RequestBringIntoView"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Et dans votre code-behind:
private void TreeViewItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
e.Handled = true;
}
J'ai réussi à résoudre le problème en utilisant les éléments suivants:
<TreeView ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=1}}" />
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
</TreeView>
Je lie la largeur du StackPanel qui rend ici le ItemsPanel, à l'ActualWidth de ContentPresenter dans le TreeView. Cela fonctionne aussi bien avec le "hacké" Stretching TreeView par: http://blogs.msdn.com/b/jpricket/archive/2008/08/05/wpf-a-stretching-treeview.aspx (J'ai modifié cette solution pour ne pas supprimer la colonne de la grille, mais pour changer la propriété Grid.Column du premier élément Decorator de 1 à 2).
Génial! Merci! – John
Matthew, j'ai mangé pour préserver le défilement vertical, et seulement empêcher le défilement horizontal en restaurant la position horizontale après un défilement causé par l'événement 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;
}
Génial. en utilisant e.Handled = true; n'a pas fonctionné pour moi, mais le vôtre le fait certainement! – mdiehl13
J'ai eu un DataGrid que je voulais faire la même opération sur et utilisé la réponse de POHB la plupart du temps. J'ai dû le modifier pour ma solution. Le code est montré ci-dessous. La grille de données est une grille de données 2 x 2 avec la première colonne étant mince et la seconde étant très large (1000+). La première colonne est gelée. J'espère que ça aide quelqu'un. -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;
}
J'ai eu un problème similaire. Je devais empêcher le défilement horizontal mais conserver le défilement vertical. Ma solution est de gérer la méthode OnRequestBringIntoView
comme je veux qu'elle se comporte. J'ai créé un ResourceDictionary
pour un et ajouté EventSetters
pour OnSelected
et OnRequestBringIntoView
méthodes.
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;
}
}
}
@ solution de lena de préserver le défilement vertical qui fonctionne le mieux pour moi. Je l'ai Iterated sur un peu:
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;
}
Ce que cela fait est de laisser le défilement ScrollViewer normalement si l'article est pas déjà dans la fenêtre verticalement. Cependant, pour le cas "agaçant" réel (où l'élément est déjà visible), il définit e.Handled sur true, empêchant ainsi le défilement horizontal.
Pour offrir une version légèrement simplifiée de la réponse de @ lena:
Pour faire défiler verticalement tout en préservant la position de défilement horizontal, et sans effets secondaires indésirables, dans le XAML, ajouter des gestionnaires d'événements pour RequestBringIntoView et sélectionnés
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="RequestBringIntoView" Handler="TreeViewItem_RequestBringIntoView"/>
<EventSetter Event="Selected" Handler="OnSelected"/>
...
Dans le code derrière, ajoutez deux gestionnaires d'événements:
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. Empêcher le défilement horizontal avec javascript?
- 2. Pouvez-vous désactiver le défilement horizontal automatique dans Eclipse?
- 3. Défilement horizontal dans Datagridview
- 4. Défilement horizontal?
- 5. jQuery.ScrollTo/jQuery.SerialScroll Défilement horizontal
- 6. Comment désactiver le défilement horizontal dans uiwebview?
- 7. touchpad défilement horizontal dans emacs
- 8. Défilement horizontal automatisé dans jQuery
- 9. Empêcher l'auto-défilement dans RichTextBox
- 10. Défilement horizontal CGrigCtrl
- 11. html défilement horizontal
- 12. script de défilement horizontal
- 13. iPhone Défilement horizontal
- 14. défilement horizontal? javascript
- 15. GridView avec défilement horizontal
- 16. Contrôles de taille automatique dans .NET CF pour éviter le défilement horizontal?
- 17. DataGridView Glisser-Déposer avec le défilement auto-horizontal
- 18. défilement rapide dans Virtual Treeview
- 19. Comment désactiver le défilement horizontal d'UIWebview?
- 20. Comment arrêter le défilement horizontal par programme?
- 21. Empêcher le redimensionnement horizontal d'une fenêtre SWT
- 22. Comment appliquer le défilement horizontal sur UITextView?
- 23. WPF ListBox contrôle le défilement horizontal dans le code
- 24. WP7 Empêcher le défilement ListBox
- 25. Div avec défilement horizontal seulement
- 26. Défilement horizontal avec la molette de défilement dans Eclipse
- 27. Défilement horizontal dans une fenêtre bash
- 28. Jquery: calcule automatiquement la largeur div pour empêcher le défilement horizontal
- 29. Défilement horizontal d'un PDF dans UIWebView
- 30. Indicateur de défilement horizontal UITableView
Est-il possible de conserver le défilement vertical et seulement prévenir horiz avez-vous défilé? –
pour @MatthewPirocchi et d'autres qui ont le même problème: on dirait que j'ai trouvé une solution http://stackoverflow.com/a/34269542/692829 – lena
Une nouvelle solution, plus simple, pour permettre le défilement vertical sans changer le décalage du rouleau horizontal (avec pas d'effets secondaires indésirables), voir cette réponse: http://stackoverflow.com/questions/3225940/prevent-automatic-horizontal-scroll-in-treeview/34269542#42238409 –