Не отображаются элементы с видимостью = свернуто в 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 заключается в том, что когда я устанавливаю элемент в коллекции на скрытый, идентификатор исчезает из GridView но оставляет пустое место, поэтому в GridView,

Есть идеи, как это решить? Может быть, то же самое редактирование в стиле XAML?

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

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

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

3 ответа

Решение

Проблема в GridView"s ItemsPanel,

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

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

После того, как вы обновили свой GridViews 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;
    }

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

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

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

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

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

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

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