wpf - WrapPanel中动态调整ItemWidth
问题描述
我正在使用 WPF MVVM。我有以下代码:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ListView ItemsSource="{Binding ItemCollection}" Height="160" Width="810">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="500" Height ="150" ItemWidth="100" ItemHeight="30"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Checked}">
<TextBlock Text="{Binding Label}"/>
</CheckBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
代码显示每个CheckBox
宽度为 100。由于其大小和(500 / 100) ,每行WrapPanel
最多可以包含 5 个es。CheckBox
ItemWidth
我有多个CheckBox
不同宽度的。
- 大多数复选框的宽度 <=100
- 一个复选框的宽度等于 280
- 将来我可能会有一个宽度 >300 且 <=400 的复选框
我不想ItemWidth
明确地将其设置为 280,因为大多数项目都较小。相反,我希望每个CheckBox
都占用 100 倍的空间来显示其所有内容。如果当前行中WrapPanel
没有足够的空间,则将其移至下一行。
对于上面的样本宽度,我期望这一点。
- 宽度 <= 100:占用 1 个项目空间(宽度 = 100)
- 宽度 <= 280:占用 3 个项目空间(宽度 = 300)
- 宽度 > 300 且 <= 400:占用 4 个项目空间(宽度 = 400)
我怎样才能做到这一点?
解决方案
明确定义所有项目的ItemWidth
宽度。
一个 Double,表示WrapPanel 中包含的所有项目的统一宽度。默认值为 NaN。
不要 设置. _ ItemWidth
然后每个项目占据其单独的大小。
WrapPanel 的子元素可以显式设置其宽度属性。ItemWidth 指定 WrapPanel 为子元素保留的布局分区的大小。因此,ItemWidth 优先于元素自身的 width。
现在,如果您没有明确定义项目的宽度,它们的大小将适合其内容,但不与100
. 不支持将项目自动缩放到定义大小的倍数WrapPanel
。
如果您想启用这种动态调整大小,则必须创建自定义换行面板,或者您可以编写自定义行为。我向您展示了后者的示例,因为它可重用且更灵活。为此,我使用Microsoft.Xaml.Behaviors.Wpf
包含基类的 NuGet 包。
public class AlignWidthBehavior : Behavior<FrameworkElement>
{
public static readonly DependencyProperty AlignmentProperty = DependencyProperty.Register(
nameof(Alignment), typeof(double), typeof(AlignWidthBehavior), new PropertyMetadata(double.NaN));
public double Alignment
{
get => (double)GetValue(AlignmentProperty);
set => SetValue(AlignmentProperty, value);
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.LayoutUpdated += OnLayoutUpdated;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.LayoutUpdated -= OnLayoutUpdated;
}
private void OnLayoutUpdated(object sender, EventArgs e)
{
var size = AssociatedObject.ActualWidth;
var alignment = Alignment;
var isAligned = size % alignment < 10E-12;
if (!double.IsNaN(alignment) && !isAligned)
AssociatedObject.Width = Math.Ceiling(size / alignment) * alignment;
}
}
当项目的布局发生变化时,会触发此行为。然后它检查关联项的宽度是否与属性给定的值对齐,Alignment
如果不是则调整它。
<DataTemplate>
<CheckBox IsChecked="{Binding Checked}">
<b:Interaction.Behaviors>
<local:AlignWidthBehavior Alignment="100"/>
</b:Interaction.Behaviors>
<TextBlock Text="{Binding Label}"/>
</CheckBox>
</DataTemplate>
您必须附加 XAML 中的行为,如上所示,并将 设置Alignment
为您想要的值,并且不要忘记ItemWidth
从WrapPanel
.
推荐阅读
- python - 如果值是类似字典的格式,则从熊猫系列中提取数据
- python-3.x - python3烧瓶:如何在html中显示json结果
- ruby-on-rails - Rails HTML 到 PDF 使用 puppeteer(无头 chrome),如何将 html 发送到 puppeteer
- c++ - 如何将 const void* 转换为 unsigned int?
- javascript - 在 JS 中绘制一个时间复杂度最小的带边框的正方形
- python - python WebUI安装上的属性错误
- css - 使用平移变换停止水平滚动
- python - 如何让python计算一个目录中有多少个文件?
- python - python格式的文件
- vagrant - vagrant box 中止,上不去