WPF:调整项目大小以使所有项目可见
我有以下代码:WPF:调整项目大小以使所有项目可见,wpf,xaml,Wpf,Xaml,我有以下代码: <ItemsControl ItemsSource="{Binding SubItems}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal"></WrapPanel> </ItemsPanelTemplate> <
<ItemsControl ItemsSource="{Binding SubItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Image Source="{Binding Image}" ></Image>
<TextBlock Text="{Binding Name}" Grid.Row="1" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
当前,如果我运行此代码,每个项目(网格)都会尝试占用全部可用空间,在我的子项目集合中的20多个项目中,我只有1-2个项目可见
如果我将MaxWidth
设置为我的网格,我会看到所有的窗口,但是当我最大化窗口时,我有很多可用空间
如果我没有设置任何宽度,我会:
如果我设置了宽度并增加了大小,我会:
我们的目标是拥有类似于第二种情况的东西,但不必设置宽度,如果我增加窗口大小,就可以缩放它
Edit2
我尝试使用UniformGrid,但有两个问题。对于两个元素,它似乎绝对希望有4列和3行。即使使用3列4行也会更好:
此外,当窗口缩小时,图像将被剪切:
您需要更改行定义
,使其看起来更像这样
<RowDefinition Height="*"/>
您的一行被设置为Auto
,这将尝试只填充它所需的空间。另一个设置为*
,这将自动拉伸以填充所有空间
请注意,也不需要键入
,只需以/>
结尾即可。此链接可能对您特别有用
你可以试试这个
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
如果没有其他帮助,请考虑编写自己的面板。我现在没有时间做一个完整的解决方案,但是考虑一下。
首先,以您想要的方式平铺矩形和正方形不是很简单。这就是所谓的包装问题,通常很难找到解决方案(取决于具体问题)。我已使用算法从以下问题中找到近似的磁贴大小:
当面板的给定宽度和高度为正方形时,其余部分更容易:
公共类可调整包装面板:面板{
受保护的覆盖尺寸测量覆盖(尺寸可用尺寸){
//获取瓷砖大小
var tileSize=GetTileSize((int)availableSize.Width,(int)availableSize.Height,this.InternalChildren.Count);
foreach(此.InternalChildren中的UIElement子元素){
//用每个孩子应该占据的正方形来测量他们
测量(新尺寸(瓷砖大小,瓷砖大小));
}
返回可用性;
}
受保护的替代尺寸排列替代(尺寸最终化){
var tileSize=GetTileSize((int)finalSize.Width,(int)finalSize.Height,this.InternalChildren.Count);
int x=0,y=0;
foreach(此.InternalChildren中的UIElement子元素)
{
//摆正
排列(新矩形(新点(x,y),新大小(平铺大小,平铺大小));
x+=波浪形;
如果(x+tileSize>=finalSize.Width){
//如果需要移动到下一排,请这样做
x=0;
y+=波浪形;
}
}
返回最终化;
}
int GetTileSize(int-width、int-height、int-tileCount)
{
if(宽度*高度
创建数据模板,如下所示:
<DataTemplate>
<Grid Height="{Binding RelativeSource={RelativeSource Self},Path=ActualWidth,Mode=OneWay}">
<Grid.Width>
<MultiBinding Converter="{StaticResource Converter}">
<Binding RelativeSource="{RelativeSource AncestorType=ItemsControl}" Path="ActualWidth" Mode="OneWay" />
<Binding RelativeSource="{RelativeSource AncestorType=ItemsControl}" Path="ActualHeight" Mode="OneWay" />
<Binding RelativeSource="{RelativeSource AncestorType=ItemsControl}" Path="DataContext.SubItems.Count" />
<Binding RelativeSource="{RelativeSource AncestorType=ItemsControl}" Path="ActualWidth" />
</MultiBinding>
</Grid.Width>
<Grid.RowDefinitions>
转换器:
公共类转换器:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,System.Globalization.CultureInfo区域性)
{
double TotalWidth=System.Convert.ToDouble(值[0]),TotalHeight=System.Convert.ToDouble(值[1]);
int TotalItems=System.Convert.ToInt32(值[2]);
var TotalArea=总宽度*总高度;
var AREA SOFANITEM=总面积/总项目;
var SideOfitem=Math.Sqrt(A
public class Converter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double TotalWidth = System.Convert.ToDouble(values[0]), TotalHeight = System.Convert.ToDouble(values[1]);
int TotalItems = System.Convert.ToInt32(values[2]);
var TotalArea = TotalWidth * TotalHeight;
var AreasOfAnItem = TotalArea / TotalItems;
var SideOfitem = Math.Sqrt(AreasOfAnItem);
var ItemsInCurrentWidth = Math.Floor(TotalWidth / SideOfitem);
var ItemsInCurrentHeight = Math.Floor(TotalHeight / SideOfitem);
while (ItemsInCurrentWidth * ItemsInCurrentHeight < TotalItems)
{
SideOfitem -= 1;//Keep decreasing the side of item unless every item is fit in current shape of window
ItemsInCurrentWidth = Math.Floor(TotalWidth / SideOfitem);
ItemsInCurrentHeight = Math.Floor(TotalHeight / SideOfitem);
}
return SideOfitem;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}