Невозможно предотвратить автоматическую горизонтальную прокрутку на TreeView в базовом классе при выборе элемента в Silverlight - PullRequest
2 голосов
/ 26 октября 2011

Я пытаюсь предотвратить автоматическую горизонтальную прокрутку элемента дерева при выборе его в Silverlight. И я пытаюсь сделать это в базовом классе.

До сих пор я не смог справиться с этим. Я попробовал следующий код, но он выполняется, а затем, когда я его выбираю, все равно просто прокручивается.

using System.Windows;
using System.Windows.Controls;

namespace MyControls
{
    public class CustomTreeView : TreeView
    {
        private ScrollViewer _scrollViewer;

        protected override void OnSelectedItemChanged(RoutedPropertyChangedEventArgs<object> e)
        {
            base.OnSelectedItemChanged(e);
            _scrollViewer.ScrollToHorizontalOffset(0);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _scrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
        }
    }
}

На самом деле я не хочу полностью отключать прокрутку - если элемент вылетает за пределы древовидного представления, я хочу, чтобы пользователь мог прокрутить до него. Я пытаюсь сохранить дерево там, где оно находится, когда я выбираю дочерний узел, длина которого может превышать ширину экрана.

Я пробовал RequestBringIntoView на WrapPanel, но, похоже, только для WPF. Я также попытался сделать это на UpdateLayout, а также SelectedItemChanged. Все безрезультатно. Кажется, я не могу найти общего решения, от которого я мог бы получить и использовать другой класс.

У кого-нибудь есть идеи?

Спасибо!

-Ari

РЕДАКТИРОВАТЬ: Щедрость заявляет, что я должен быть в состоянии сделать это в XAML. Это была опечатка с моей стороны. Я возьму решения для кода также. Спасибо!

Ответы [ 3 ]

5 голосов
/ 29 октября 2011

То, что заставляет ScrollViewer прокручиваться, заключается в том, что каждый раз, когда изменяется выбор TreeView, вызывается ScrollIntoView (внутри исходного кода TreeView),

this.ItemsControlHelper.ScrollIntoView(container.HeaderElement ?? container);

и он в основном пытается прокрутить либо заголовок, либо весь TreeViewItem влево.Сначала я подумал, что вы можете изменить оба стиля TreeView и TreeViewItem, удалив все левые Margin и сделав заголовок таким же левым полем, что и кнопка расширения.Тем не менее, это решение работает только для элементов первого уровня, как и на втором уровне, перед элементом есть отступ, так что если вы щелкнете по нему, он снова прокрутится.

Так что я думаю, что чистого решения xaml не существует.Проще всего решить эту проблему, учитывая, что у вас уже есть пользовательский элемент управления вместо вызова (я думаю, что есть проблема с синхронизацией, и поэтому этот код не работает)

_scrollViewer.ScrollToHorizontalOffset(0); 

youdo

var scrollableRegions = _scrollViewer.GetVisualDescendants().OfType<IScrollInfo>();
            foreach (var region in scrollableRegions)
            {
                region.SetHorizontalOffset(0);
            }

Если вы действительно предпочитаете решения xaml, вы можете также поместить этот код в поведение или присоединенное свойство и просто вставить его, используя Blend.

Сказав все это,другое решение, которое я лично считаю более подходящим, и я использовал его в своем приложении: полностью отключить горизонтальную полосу прокрутки и использовать TextTrimming="WordEllipsis" для всех моих TextBlocks внутри TreeViewItems, чтобы указать пользователю, что текста больше.Также укажите GridSplitter, чтобы позволить пользователю изменять размер содержимого TreeView, чтобы видеть полный текст, вместо прокрутки назад и вперед по горизонтали.Но это только мое мнение.

Надеюсь, это поможет!:)

0 голосов
/ 05 июня 2017

Поздний ответ для тех, кто не удовлетворен вышеуказанными решениями:

Как объяснено на в этом блоге разработчика MSDN , древовидное представление прокручивается, потому что TreeViewItem вызывает свой метод BringIntoView при выборе. Событие можно отменить, переопределив его обработчик и пометив его как Обработанный, следующим образом:

XAML:

<TreeView>
  <TreeView.Resources>
    <Style TargetType="TreeViewItem">
      <EventSetter Event="RequestBringIntoView" Handler="TreeViewItem_RequestBringIntoView"/>
    </Style>
  </TreeView.Resources>
</TreeView>

обработчик:

void TreeViewItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) {
  e.Handled = true;
}

Подход еще имеет недостаток: прямые вызовы tvi.BringIntoView() также перестают работать, но его можно обойти, установив логический флаг перед вызовом BringIntoView, проверив его в обработчике и сбросив его после вызова.

0 голосов
/ 29 октября 2011

Я думаю, что в вашем случае лучший способ добиться этого - полностью убрать средство просмотра прокрутки внутри древовидного представления путем создания стиля «голое древовидное представление», подобного этому:

    <Style x:Key="TreeViewStyle1" TargetType="sdk:TreeView">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="sdk:TreeView">
                    <Grid>
                        <ItemsPresenter Margin="5,5,19,19" d:LayoutOverrides="Width, Height"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Затем просто примените шаблон к вашему средству просмотра прокрутки и оберните его внешним средством просмотра с прокруткой следующим образом:

<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource TreeViewSampleData}}">
    <ScrollViewer>
        <sdk:TreeView ItemsSource="{Binding RootCollection}" ItemTemplate="{StaticResource FirstLevelTemplate}" Style="{StaticResource TreeViewStyle1}"/>
    </ScrollViewer>
</Grid>

Теперь древовидная структура не имеет возможности взаимодействовать со средством просмотра прокрутки, и поэтому она не сможет прокручиваться при выборе элемента.

Имейте в виду, что это устраняет любую автоматическую прокрутку, и теперь возможна только ручная прокрутка. Вы по-прежнему можете добавить собственную автоматическую прокрутку, используя поведения или TargetedTriggerAction (s).

Убедитесь, что в древовидном представлении не заданы какие-либо размеры, чтобы оно свободно росло в средстве просмотра прокрутки.

Надеюсь, это поможет.

...