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