如何根据 window 宽度自动调整 GridView 项目的外观和宽度
How to auto-adjust GridView item appearance and width depending on window width
我正在尝试让我的 GridView
根据屏幕宽度自动调整其项目的外观,但每次我拍摄我的应用程序 window 时,GridView
项目都会保留靠得太近了。如何确保每个 GridView
项目都出现在自己的行上,并在悬停时像 ListView
项目一样突出显示整行,当 window 对齐到一侧或小于一侧时一定的宽度(比如 720 - 这通常用于 MasterDetailsView - CompactModeThresholdWidth="720")?
宽window
抢购window
快照 window(预期结果)
MainPage.xaml
<Page
x:Class="MyApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:MyApp.Models"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,20" Grid.Row="0">
<TextBlock Text="Hello World"/>
</StackPanel>
<GridView Grid.Row="1"
IsItemClickEnabled="True"
ItemsSource="{x:Bind GridItems}"
ItemClick="GridView_ItemClick">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<data:MyGridViewPanel/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:GridItemMain">
<StackPanel Orientation="Horizontal">
<TextBlock Grid.Column="0"
Text="{Binding Icon}"
Style="{StaticResource TitleTextBlockStyle}"
FontFamily="Segoe MDL2 Assets"/>
<TextBlock Grid.Column="1"
Text="{Binding Title}"
Style="{StaticResource TitleTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public List<GridItemMain> GridItems;
public MainPage()
{
this.InitializeComponent();
GridItems = GridItemManager.GetGridItems();
}
}
MainGridItem.cs
public class MainGridItem
{
public string Icon { get; set; }
public string Title { get; set; }
}
public class GridItemManager
{
public static List<MainGridItem> GetGridItems()
{
var gridItems = new List<MainGridItem>();
gridItems.Add(new MainGridItem { Icon = "\uE770", Title = "System" });
gridItems.Add(new MainGridItem { Icon = "\uE772", Title = "Devices" });
gridItems.Add(new MainGridItem { Icon = "\uEC75", Title = "Phone" });
gridItems.Add(new MainGridItem { Icon = "\uE774", Title = "Network & Internet" });
gridItems.Add(new MainGridItem { Icon = "\uE771", Title = "Personalisation" });
return gridItems;
}
}
MyGridViewPanel.cs
public class MyGridViewPanel : Panel
{
private double _maxWidth;
private double _maxHeight;
protected override Size ArrangeOverride(Size finalSize)
{
var x = 0.0;
var y = 0.0;
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
var newpos = new Rect(0, y, width, _maxHeight);
child.Arrange(newpos);
y += _maxHeight;
}
return finalSize;
}
else {
foreach (var child in Children)
{
if ((_maxWidth + x) > finalSize.Width)
{
x = 0;
y += _maxHeight;
}
var newpos = new Rect(x, y, _maxWidth, _maxHeight);
child.Arrange(newpos);
x += _maxWidth;
}
return finalSize;
}
}
protected override Size MeasureOverride(Size availableSize)
{
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
child.Measure(new Size(width, availableSize.Height));
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
return new Size(width, _maxHeight * Children.Count);
}
else {
foreach (var child in Children)
{
child.Measure(availableSize);
var desirtedwidth = child.DesiredSize.Width;
if (desirtedwidth > _maxWidth)
_maxWidth = desirtedwidth;
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
var itemperrow = Math.Floor(availableSize.Width / _maxWidth);
var rows = Math.Ceiling(Children.Count / itemperrow);
return new Size(itemperrow * _maxWidth, _maxHeight * rows);
}
}
}
更新
如果想在window小于720px时每行显示一个item,可以在ArrangeOverride和MeasureOverride方法中获取当前window的宽度,然后resize项目并重新布局每个项目以在每一行中显示它们。例如:
MyGridViewPanel.cs
public class MyGridViewPanel : Panel
{
private double _maxWidth;
private double _maxHeight;
protected override Size ArrangeOverride(Size finalSize)
{
var x = 0.0;
var y = 0.0;
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
var newpos = new Rect(0, y, width, _maxHeight);
child.Arrange(newpos);
y += _maxHeight;
}
return finalSize;
}
else {
foreach (var child in Children)
{
if ((_maxWidth + x) > finalSize.Width)
{
x = 0;
y += _maxHeight;
}
var newpos = new Rect(x, y, _maxWidth, _maxHeight);
child.Arrange(newpos);
x += _maxWidth;
}
return finalSize;
}
}
protected override Size MeasureOverride(Size availableSize)
{
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
child.Measure(new Size(width, availableSize.Height));
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
return new Size(width, _maxHeight * Children.Count);
}
else {
foreach (var child in Children)
{
child.Measure(availableSize);
var desirtedwidth = child.DesiredSize.Width;
if (desirtedwidth > _maxWidth)
_maxWidth = desirtedwidth;
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
var itemperrow = Math.Floor(availableSize.Width / _maxWidth);
var rows = Math.Ceiling(Children.Count / itemperrow);
return new Size(itemperrow * _maxWidth, _maxHeight * rows);
}
}
}
我正在尝试让我的 GridView
根据屏幕宽度自动调整其项目的外观,但每次我拍摄我的应用程序 window 时,GridView
项目都会保留靠得太近了。如何确保每个 GridView
项目都出现在自己的行上,并在悬停时像 ListView
项目一样突出显示整行,当 window 对齐到一侧或小于一侧时一定的宽度(比如 720 - 这通常用于 MasterDetailsView - CompactModeThresholdWidth="720")?
宽window
抢购window
快照 window(预期结果)
MainPage.xaml
<Page
x:Class="MyApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:MyApp.Models"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,20" Grid.Row="0">
<TextBlock Text="Hello World"/>
</StackPanel>
<GridView Grid.Row="1"
IsItemClickEnabled="True"
ItemsSource="{x:Bind GridItems}"
ItemClick="GridView_ItemClick">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<data:MyGridViewPanel/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:GridItemMain">
<StackPanel Orientation="Horizontal">
<TextBlock Grid.Column="0"
Text="{Binding Icon}"
Style="{StaticResource TitleTextBlockStyle}"
FontFamily="Segoe MDL2 Assets"/>
<TextBlock Grid.Column="1"
Text="{Binding Title}"
Style="{StaticResource TitleTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public List<GridItemMain> GridItems;
public MainPage()
{
this.InitializeComponent();
GridItems = GridItemManager.GetGridItems();
}
}
MainGridItem.cs
public class MainGridItem
{
public string Icon { get; set; }
public string Title { get; set; }
}
public class GridItemManager
{
public static List<MainGridItem> GetGridItems()
{
var gridItems = new List<MainGridItem>();
gridItems.Add(new MainGridItem { Icon = "\uE770", Title = "System" });
gridItems.Add(new MainGridItem { Icon = "\uE772", Title = "Devices" });
gridItems.Add(new MainGridItem { Icon = "\uEC75", Title = "Phone" });
gridItems.Add(new MainGridItem { Icon = "\uE774", Title = "Network & Internet" });
gridItems.Add(new MainGridItem { Icon = "\uE771", Title = "Personalisation" });
return gridItems;
}
}
MyGridViewPanel.cs
public class MyGridViewPanel : Panel
{
private double _maxWidth;
private double _maxHeight;
protected override Size ArrangeOverride(Size finalSize)
{
var x = 0.0;
var y = 0.0;
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
var newpos = new Rect(0, y, width, _maxHeight);
child.Arrange(newpos);
y += _maxHeight;
}
return finalSize;
}
else {
foreach (var child in Children)
{
if ((_maxWidth + x) > finalSize.Width)
{
x = 0;
y += _maxHeight;
}
var newpos = new Rect(x, y, _maxWidth, _maxHeight);
child.Arrange(newpos);
x += _maxWidth;
}
return finalSize;
}
}
protected override Size MeasureOverride(Size availableSize)
{
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
child.Measure(new Size(width, availableSize.Height));
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
return new Size(width, _maxHeight * Children.Count);
}
else {
foreach (var child in Children)
{
child.Measure(availableSize);
var desirtedwidth = child.DesiredSize.Width;
if (desirtedwidth > _maxWidth)
_maxWidth = desirtedwidth;
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
var itemperrow = Math.Floor(availableSize.Width / _maxWidth);
var rows = Math.Ceiling(Children.Count / itemperrow);
return new Size(itemperrow * _maxWidth, _maxHeight * rows);
}
}
}
更新
如果想在window小于720px时每行显示一个item,可以在ArrangeOverride和MeasureOverride方法中获取当前window的宽度,然后resize项目并重新布局每个项目以在每一行中显示它们。例如:
MyGridViewPanel.cs
public class MyGridViewPanel : Panel
{
private double _maxWidth;
private double _maxHeight;
protected override Size ArrangeOverride(Size finalSize)
{
var x = 0.0;
var y = 0.0;
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
var newpos = new Rect(0, y, width, _maxHeight);
child.Arrange(newpos);
y += _maxHeight;
}
return finalSize;
}
else {
foreach (var child in Children)
{
if ((_maxWidth + x) > finalSize.Width)
{
x = 0;
y += _maxHeight;
}
var newpos = new Rect(x, y, _maxWidth, _maxHeight);
child.Arrange(newpos);
x += _maxWidth;
}
return finalSize;
}
}
protected override Size MeasureOverride(Size availableSize)
{
double width = Window.Current.Bounds.Width;
if (width <= 720)
{
foreach (var child in Children)
{
child.Measure(new Size(width, availableSize.Height));
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
return new Size(width, _maxHeight * Children.Count);
}
else {
foreach (var child in Children)
{
child.Measure(availableSize);
var desirtedwidth = child.DesiredSize.Width;
if (desirtedwidth > _maxWidth)
_maxWidth = desirtedwidth;
var desiredheight = child.DesiredSize.Height;
if (desiredheight > _maxHeight)
_maxHeight = desiredheight;
}
var itemperrow = Math.Floor(availableSize.Width / _maxWidth);
var rows = Math.Ceiling(Children.Count / itemperrow);
return new Size(itemperrow * _maxWidth, _maxHeight * rows);
}
}
}