GridView с двумя столбцами, шириной заливки
Результат, который я хочу достичь, довольно прост, список с двумя столбцами, одинаковыми по ширине. В Windows Phone 7/8 это может быть легко достигнуто с помощью ListBox
с WrapPanel
как ItemsPanel
и установки ItemWidth
на 240 (поскольку ширина экрана равна 480).
Теперь я пишу универсальное приложение, но здесь проблема заключается в том, что на экране не гарантируется ширина 480 (даже не для телефона), поэтому я не могу установить ItemWidth
поскольку я хочу, чтобы он заполнил ширину экрана. Я смог добиться почти желаемого эффекта, используя следующий XAML
:
Это дает следующий результат:
- События WPF в ResourceDictionary для ControlTemplate
- Являются ли "{Binding Path =.}" И "{Binding}" действительно равными
- Привязка OneWayToSource от свойства readonly в XAML
- Загрузка XAML во время выполнения?
- DataTrigger не изменяет свойство Text
Как видно, он успешно дает 2 столбца с равной шириной, НО Grid
в GridView.ItemTemlate
не заполняет всю ширину каждого столбца. Я попытался установить HorizontalAlignment="Stretch"
на обоих gridх и на GridView
сам без каких-либо успехов. Кто-нибудь имеет представление об этом?
- Ошибка привязки элемента ElementName
- Как создать вкладки трапеции в элементе управления вкладками WPF
- Этот тип CollectionView не поддерживает изменения в SourceCollection из streamа, отличного от streamа Dispatcher
- Конвертер связыванияПараметр
- WPF TreeView HierarchicalDataTemplate - привязка к объекту с несколькими дочерними коллекциями
- WinRT и региональные настройки. Правильный способ форматирования дат и чисел на основе региональных настроек пользователя?
- Как получить размер текущего экрана в WPF?
- URI «clr-namespace» относится к пространству имен, которое не входит в сборку
Вы можете попробовать следующее:
Другая вещь, которую вы могли бы попробовать, – это вручную установить ItemWidth
/ ItemHeight
всякий раз, когда вы получаете событие SizeChanged
в GridView
.
Если по какой-либо причине вышеуказанное не работает, вы также можете сделать то, что я делаю ниже, и обновить Value
обоих ресурсов SizeChanged
событий SizeChanged
:
...
Где DoubleViewModel
:
public class DoubleViewModel : BindableBase { #region Value /// /// Backing field for the Value property. /// private double value; /// /// Gets or sets a value indicating the value. /// public double Value { get { return this.value; } set { this.SetProperty(ref this.value, value); } } #endregion }
Мое решение:
Код:
private void GridView_SizeChanged(object sender, SizeChangedEventArgs e) { var panel = (ItemsWrapGrid)MyGridView.ItemsPanelRoot; panel.ItemWidth =panel.ItemHeight= e.NewSize.Width / 2; }
Решение, которое я использовал, было основано на предложении Филиппа Скакунса, но небольшая другая реализация, сделав повторное использование User Control с таким поведением. Пользовательский элемент управления имеет (среди прочих) свойства Columns
и ItemsSource
. Я изменяю ItemWidth
элемента ItemsWrapGrid
вместо ширины ItemTemplate
и делаю это непосредственно в SizeChanged
событий SizeChanged
.
Для этого мне также понадобилось использовать ItemsWrapGrid
вместо WrapGrid
. XAML для конечного пользователя:
И для кода:
using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace MyProject.CustomControls { public sealed partial class ColumnGridView : UserControl { public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(ColumnGridView), new PropertyMetadata(null)); public DataTemplate ItemTemplate { get { return (DataTemplate)GetValue(ItemTemplateProperty); } set { SetValue(ItemTemplateProperty, value); } } public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(ColumnGridView), new PropertyMetadata(null)); public object ItemsSource { get { return (object)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(int), typeof(ColumnGridView), new PropertyMetadata(1)); public int Columns { get { return (int)GetValue(ColumnsProperty); } set { if (value <= 0) throw new ArgumentOutOfRangeException("Columns must be greater than 0"); SetValue(ColumnsProperty, value); } } public ColumnGridView() { this.InitializeComponent(); } private void ItemsWrapGrid_SizeChanged(object sender, SizeChangedEventArgs e) { ItemsWrapGrid itemsWrapGrid = sender as ItemsWrapGrid; if (itemsWrapGrid != null) { itemsWrapGrid.ItemWidth = e.NewSize.Width / Columns; } } } }
Мне удалось решить что-то очень похожее, просто привязав значение Item Width к родительскому ActualWidth, например:
В качестве альтернативы вы можете использовать Loaded-Event из своего WrapGrid
чтобы установить хотя бы ItemWidth
XAML
Codebehind
private void MyWrapGrid_Loaded(object sender, RoutedEventArgs e) { var wg = sender as WrapGrid; wg.ItemWidth = MyGrid.ActualWidth; }