我想重新记录Windows中带有图标视图的文件夹的行为。当我们水平调整大小时,直到新图标适合当前行,边距会增加,以便当前行中的所有图标按比例填充整个宽度。
我的整个XAML代码如下。目前我的应用程序的行为就像你在这两张图片中看到的那样:
如何拉伸元素之间的边距,以便始终填充整行?
<Window x:Class="drag_out_test.MainWindow"
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:local="clr-namespace:drag_out_test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<UniformGrid>
<ListBox Name="FileListBox"
MouseMove="FileView_MouseMove"
MouseDown="FileListBox_MouseDown"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Padding="10">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
MaxWidth="{Binding ActualWidth,ElementName=FileListBox}">
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Margin"
Value="5,0,5,0" />
<Setter Property="Padding"
Value="5,0,5,0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Rectangle Width="50" Height="50" Fill="Black">
</Rectangle>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UniformGrid>
</Window>
答案 0 :(得分:0)
这是自定义控件的最简单示例。只有水平方向和探险家视图。
public class StretchyWrapPanel : Panel
{
// Default vertical offset
const int ElementVerticalOffset = 5;
protected override Size MeasureOverride(Size constraint)
{
Size currentLineSize = new Size();
Size panelSize = new Size();
foreach (UIElement element in InternalChildren)
{
// Compute element size
element.Measure(constraint);
Size desiredSize = element.DesiredSize;
// Go to new line
if (currentLineSize.Width + desiredSize.Width > constraint.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height + ElementVerticalOffset;
currentLineSize = desiredSize;
// If width of element is more than our constrait -> go to new line
if (desiredSize.Width > constraint.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height + ElementVerticalOffset;
currentLineSize = new Size();
}
}
// If element can be placed in line
else
{
currentLineSize.Width += desiredSize.Width;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
}
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
return panelSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
var currentLineSize = new Size();
Size panelSize = new Size();
double offsetLeft = 0;
double offsetTop = 0;
foreach (UIElement element in InternalChildren)
{
Size desiredSize = element.DesiredSize;
var elementCountInLine = (int)(finalSize.Width / desiredSize.Width);
int elementHorizontalOffset = (int)((finalSize.Width - elementCountInLine * desiredSize.Width) / (elementCountInLine));
if (currentLineSize.Width + desiredSize.Width + elementHorizontalOffset > finalSize.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
currentLineSize = desiredSize;
if (desiredSize.Width > finalSize.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
currentLineSize = new Size();
}
offsetLeft = 0;
offsetTop += desiredSize.Height + ElementVerticalOffset;
}
else
{
currentLineSize.Width += desiredSize.Width + elementHorizontalOffset;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
element.Arrange(new Rect(new Point(offsetLeft, offsetTop), element.DesiredSize));
offsetLeft += desiredSize.Width + elementHorizontalOffset;
}
return finalSize;
}
}
答案 1 :(得分:0)
我修改了您的答案Pavel,然后得到了我需要的行为:
public class CustomWrapPanel : Panel
{
// Default vertical offset
const int ElementVerticalOffset = 5;
protected override Size MeasureOverride(Size constraint)
{
Size currentLineSize = new Size();
Size panelSize = new Size();
foreach (UIElement element in InternalChildren)
{
// Compute element size
element.Measure(constraint);
Size desiredSize = element.DesiredSize;
// Go to new line
if (currentLineSize.Width + desiredSize.Width > constraint.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height + ElementVerticalOffset;
currentLineSize = desiredSize;
// If width of element is more than our constrait -> go to new line
if (desiredSize.Width > constraint.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height + ElementVerticalOffset;
currentLineSize = new Size();
}
}
// If element can be placed in line
else
{
currentLineSize.Width += desiredSize.Width;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
}
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
return panelSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
var currentLineSize = new Size();
Size panelSize = new Size();
double offsetLeft = 0;
double offsetTop = 0;
foreach (UIElement element in InternalChildren)
{
Size desiredSize = element.DesiredSize;
var elementCountInLine = (int)(finalSize.Width / desiredSize.Width);
int elementHorizontalOffset = (int)((finalSize.Width - elementCountInLine * desiredSize.Width) / (elementCountInLine + 1));
if (offsetLeft == 0) { offsetLeft = elementHorizontalOffset; }
if (currentLineSize.Width + desiredSize.Width + elementHorizontalOffset > finalSize.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
currentLineSize = desiredSize;
if (desiredSize.Width > finalSize.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
currentLineSize = new Size();
}
offsetLeft = elementHorizontalOffset;
offsetTop += desiredSize.Height + ElementVerticalOffset;
}
else
{
currentLineSize.Width += desiredSize.Width + elementHorizontalOffset;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
element.Arrange(new Rect(new Point(offsetLeft, offsetTop), element.DesiredSize));
offsetLeft += desiredSize.Width + elementHorizontalOffset;
}
return finalSize;
}
}