MasterDetailView UWP - доступ к ListView (или сделать его прокруткой)

Недавно я обнаружил UWP Community Toolkit, и мне он понравился. Я использую сейчас MasterDetailView и это почти идеально подходит для того, что мне нужно: но в нем отсутствует одна важная вещь: я не могу получить доступ к внутреннему "ListView".

В моем приложении у меня есть две кнопки: вперед и назад, и, нажимая их, я просто иду вперед и назад в списке. Я нашел трюк для доступа к элементу prev/next, выполнив следующее:

public void GoForward()
    {
        if (MasterDetailView.Items.Count > 0)
        {
            bool isNextGood = false;
            MyItem selectedItem = MasterDetailView.Items[MasterDetailView.Items.Count - 1] as MyItem;

            foreach (var v in MasterDetailView.Items)
            {
                if (isNextGood)
                {
                    selectedItem = v as MyItem;
                    break;
                }

                if (v == MasterDetailView.SelectedItem)
                    isNextGood = true;
            }

            MasterDetailView.SelectedItem = selectedItem;
        }
    }

Это только потому, что я не могу получить доступ к "SelectedIndex", и у меня есть только SelectedItem доступен. Теперь, очевидно, не все элементы могут быть видны одновременно, поэтому MasterDetailView предоставляет боковой ListView с полосой прокрутки. При нажатии кнопок "следующий / предыдущий" SelectedItem изменяется, но не прокручивает выбранный элемент: выбор переходит вперед / назад, но список блокируется. Это дает очень отрицательный отзыв, потому что я потерял свой выбор где-то в списке, и я должен искать его.

Как мне хоть это решить? Я пытаюсь это подходит:


1) Найти стиль для MasterDetailView. Внутри я нашел ListViewStyle, поэтому я попытался поместить в простое событие "SelectionChanged" и обработать его в App.xaml.cs.

<ListView x:Name="MasterList"
                                      Grid.Row="1"
                                      IsTabStop="False"
                                      ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
                                      ItemTemplate="{TemplateBinding ItemTemplate}"
                                      ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                                      ItemsSource="{TemplateBinding ItemsSource}"
                                      SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                      SelectionChanged="MasterList_SelectionChanged"/>

CS:

private void MasterList_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ListView list = sender as ListView;
        list.ScrollIntoView(list.SelectedItem);
    }

Но, как сказано, "События не могут быть установлены в XAML-файле класса Application".


2) Подумайте о том, чтобы взять родителя SelectedItem: я попытался преобразовать SelectedItem в ListViewItem, а затем получить доступ к родителю, но при первом преобразовании это не удалось, так как SelectedItem, похоже, не является ListViewItem, но он имеет тип "MyItem". Таким образом, я не могу получить доступ к родителю.

private void MasterDetailView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var item = MasterDetailView.SelectedItem as ListViewItem;
        var parent = item.Parent;
        var list = parent as ListView;
    }

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

private void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListView list = sender as ListView;
            list.ScrollIntoView(list.SelectedItem);
        }

Просто прокрутка в выделение, когда выбор произошел, но у меня нет простого ListView, но элемент управления MasterDetailView. Даже если это сделано полностью в XAML: для меня самое главное - прокрутить этот список!

Благодарю.


Решение

Этот метод фантастический. Просто скопируйте и вставьте.

public static T FindChildOfType<T>(DependencyObject root) where T : class
    {
        var queue = new Queue<DependencyObject>();
        queue.Enqueue(root);
        while (queue.Count > 0)
        {
            DependencyObject current = queue.Dequeue();
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(current); i++)
            {
                var child = VisualTreeHelper.GetChild(current, i);
                var typedChild = child as T;
                if (typedChild != null)
                {
                    return typedChild;
                }
                queue.Enqueue(child);
            }
        }
        return null;
    }

Затем просто используйте его, чтобы получить список и прокрутить его. Да детка!

private void MasterDetailView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var v = FindChildOfType<ListView>(MasterDetailView);
        v.ScrollIntoView(MasterDetailView.SelectedItem);
    }

Обратите внимание, что "MasterDerailView" - это x: имя моего элемента, а не класса.

1 ответ

Решение

Вы можете использовать реализацию FindChildOfType, чтобы получить ListView через VisualTreeHelper, как указано в этом ответе: Windows UWP - Как программно прокрутить ListView в ContentTemplate

Другие вопросы по тегам