Не показывать элементы с видимостью = Свернуто в Windows 8.1 GridView

У меня есть приложение Windows 8.1 с GridView, связанное с пользовательской (сортируемой, дедуплицируемой) наблюдаемой коллекцией. В этой коллекции я делаю тяжелую фильтрацию и устанавливаю флаг IsHidden для каждого элемента.

В шаблоне данных для элемента есть условие, делающее элемент свернутым, если флаг IsHidden имеет значение true.

<Grid Width="160" Height="280" Visibility="{Binding IsHidden, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">

Этот подход работает в Windows Phone 8.1 XAML, из-за чего элементы исчезают из ListView, но он не работает в Windows 8.1 GridView. Проблема с Windows 8.1 заключается в том, что когда я устанавливаю элемент в коллекции скрытым, id исчезает из GridView, но оставляет пустое место, поэтому в GridView есть пробел.

enter image description here

Любые идеи о том, как его решить? Может быть, такое же редактирование стиля XAML?

Вот минимальное решение для воспроизведения проблемы: https://dl.dropboxusercontent.com/u/73642/gv.zip

Я попытался привязать ширину и высоту элементов к скрытому флагу и установить его на 0, когда элемент скрыт, но это не помогло, все еще пробел в GridView.

Обновить. Один способ обхода - это фильтрация фактической привязки, но это невозможно из-за некоторых бизнес-требований.

Ответ 1

Проблема заключается в GridView ItemsPanel.

Оба ItemsWrapGrid и WrapGrid являются равномерными сетками. Все их дочерние элементы будут иметь одинаковую высоту и ширину. Вот почему, даже если вы сбрасываете ItemTemplate, пространство по-прежнему сохраняется.

Что вам действительно нужно, это WrapPanel. WINRT не имеет встроенного WrapPanel, но Джерри Никсон построил его, и вы можете его захватить из здесь.

После того, как вы обновили свой GridView ItemsPanel, вам еще нужно сделать еще одну вещь. Вам также нужно получить GridViewItem, в котором размещается ваш ItemTemplate, и установите его Visibility на Collapsed.

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        ds[5].IsHidden = true;

        await Task.Delay(1000);
        var gridViewItem =(GridViewItem)this.gv.ContainerFromIndex(5);
        gridViewItem.Visibility = Visibility.Collapsed;
    }

Я поставил немного задержку выше, чтобы сделать коллапс более очевидным.

Ответ 2

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

Я изменил ваш клик-дескриптор вместо ds.RemoveAt(5); вместо того, чтобы скрывать элемент, и элемент удаляется из представления с помощью хорошей анимации. Это кажется ожидаемым, и интересная находка.

Ответ 3

Мне нужно много времени, чтобы понять проблему, и решение прямо перед моими глазами. Вы пытаетесь скрыть сам элемент, но контейнер все еще там. Когда вы добавляете элемент в GridView, элемент обернут в контейнер товаров. из msdn:

"Когда вы добавляете элемент в элемент управления ItemsControl, элемент завернут в контейнер предметов. Например, элемент, добавленный в ListView, завернут в ListViewItem. Без виртуализации пользовательского интерфейса весь набор данных сохраняется в памяти и контейнер элементов также создается для каждого элемента в набор данных. ListView, связанный с коллекцией из 1000 элементов, будет также создайте 1000 контейнеров ListViewItem, которые хранятся в памяти."

Вам нужно отключить контейнер и создать два DataTemplate, а с помощью DataTemplateSelector вы можете выбрать, какой DataTemplate можно отключить и активировать. Проверьте эту полезную статью.