如何在 Panel 中实现设置所有子项间距

科技   2024-10-17 08:30   北京  

 如何在 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);
        }
    }
}

示例

引入 WPFDevelopersNuget


<!--<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>

参考资料
[1]

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers

[2]

码云链接: https://gitee.com/WPFDevelopersOrg/WPFDevelopers


WPF开发者
「WPF开发者」现役微软MVP,专注 WPF 和 Avalonia 技术分享与传播。
 最新文章