如何在 Panel 中实现设置所有子项间距
控件名:PanelHelper
作 者:WPFDevelopersOrg - 驚鏵
原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers
码云链接[2]:https://gitee.com/WPFDevelopersOrg/WPFDevelopers
框架支持 .NET4 至 .NET8
;Visual Studio 2022
;
在使用 WPF
时,我们发现面板 Panel
并没有提供直接设置 Spacing
的功能。为了解决这一问题,我们借鉴了 Qt
中的 Spacing
设置方法,来统一调整所有子项之间的间距。
Qt
PanelHelper 类
创建 PanelHelper
的类,继承自 DependencyObject
,用于实现依赖属性和动态更新面板子项的间距。
获取和设置间距与定义间距依赖属性
定义了一个名为 Spacing
的依赖属性,用于保存间距,当在其值发生更改时调用OnSpacingChanged
方法。
public static readonly DependencyProperty SpacingProperty =
DependencyProperty.RegisterAttached("Spacing", typeof(double), typeof(PanelHelper), new UIPropertyMetadata(0d, OnSpacingChanged));
public static double GetSpacing(DependencyObject obj)
{
return (double)obj.GetValue(SpacingProperty);
}
public static void SetSpacing(DependencyObject obj, double value)
{
obj.SetValue(SpacingProperty, value);
}
处理间距变化
如对象是面板 Panel
时则检查面板是否已IsLoaded
。如果已IsLoaded
,则更新子项的Spacing
;如果未IsLoaded
,则在面板加载完成后更新Spacing
。
private static void OnSpacingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Panel panel)
{
double newValue = (double)e.NewValue;
double oldValue = (double)e.OldValue;
if (panel.IsLoaded)
{
UpdateChildrenSpacing(panel, newValue);
}
else
{
panel.Loaded -= OnPanelLoaded;
panel.Loaded += OnPanelLoaded;
panel.SetValue(SpacingProperty, newValue);
}
}
}
处理面板加载事件
当面板 Panel
加载完成时,方法将被执行。它获取当前的Spacing
值并更新所有子项的Spacing
,然后取消事件。
private static void OnPanelLoaded(object sender, RoutedEventArgs e)
{
if (sender is Panel panel)
{
double spacing = (double)panel.GetValue(SpacingProperty);
UpdateChildrenSpacing(panel, spacing);
panel.Loaded -= OnPanelLoaded;
}
}
更新子项间距
循环面板中的所有子项,将每个子项的边距设置为指定的间距值。
private static void UpdateChildrenSpacing(Panel panel, double spacing)
{
foreach (UIElement child in panel.Children)
{
if (child is FrameworkElement frameworkElement)
{
frameworkElement.Margin = new Thickness(spacing);
}
}
}
示例
引入 WPFDevelopers
的 Nuget
包
<!--<StackPanel wd:PanelHelper.Spacing="3"/>
<WrapPanel wd:PanelHelper.Spacing="3" />
<UniformGrid wd:PanelHelper.Spacing="3"/>
<DockPanel wd:PanelHelper.Spacing="3"/>
<Grid wd:PanelHelper.Spacing="3"/>-->
<TabControl>
<TabItem Header="StackPanel">
<StackPanel wd:PanelHelper.Spacing="3">
<Button Content="Content 1" Style="{StaticResource WD.PrimaryButton}" />
<Button Content="Content 2" Style="{StaticResource WD.PrimaryButton}" />
<Button Content="Content 3" Style="{StaticResource WD.PrimaryButton}" />
</StackPanel>
</TabItem>
<TabItem Header="WrapPanel">
<WrapPanel wd:PanelHelper.Spacing="3">
<Button Content="Content 1" Style="{StaticResource WD.DangerPrimaryButton}" />
<Button Content="Content 2" Style="{StaticResource WD.DangerPrimaryButton}" />
<Button Content="Content 3" Style="{StaticResource WD.DangerPrimaryButton}" />
</WrapPanel>
</TabItem>
<TabItem Header="UniformGrid">
<UniformGrid wd:PanelHelper.Spacing="3">
<Button Content="Content 1" Style="{StaticResource WD.SuccessPrimaryButton}" />
<Button Content="Content 2" Style="{StaticResource WD.SuccessPrimaryButton}" />
<Button Content="Content 3" Style="{StaticResource WD.SuccessPrimaryButton}" />
</UniformGrid>
</TabItem>
<TabItem Header="Grid">
<Grid wd:PanelHelper.Spacing="3">
<Button
Width="200"
Height="200"
Content="Content 1"
Style="{StaticResource WD.WarningPrimaryButton}" />
<Button
Width="180"
Height="180"
Content="Content 2"
Style="{StaticResource WD.DangerPrimaryButton}" />
<Button
Width="160"
Height="160"
Content="Content 3"
Style="{StaticResource WD.SuccessPrimaryButton}" />
</Grid>
</TabItem>
</TabControl>
原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers
[2]码云链接: https://gitee.com/WPFDevelopersOrg/WPFDevelopers