WPF实现动态四宫格布局

需求描述

我们要设计一个界面,用户可以通过 CheckBox 控制哪些图表显示。图表的数量是动态的,最多可以选择显示四个图表。如果显示一个图表,它会占满整个区域;如果显示两个图表,它们会水平排列;显示三个图表时,上面两个水平排列,下面一个铺满宽度;如果显示四个图表,它们会均匀分布在四个格子中。

XAML 代码

首先,我们需要一个 Grid 布局,它将包含最多四个图表的占位区域。我们还需要一些 CheckBox 控制每个图表的显示。以下是 XAML 代码

xml 复制代码
<Window x:Class="DynamicGridLayout.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="动态四宫格布局" Height="450" Width="800">
    <Grid>
        <!-- 控制图表显示的 CheckBox -->
        <StackPanel Margin="10" HorizontalAlignment="Left" Orientation="Horizontal">
            <TextBlock Text="显示图表:" />
            <CheckBox x:Name="chbChart1" Margin="10,0,0,0" Checked="ChartShow_OnChecked" Unchecked="ChartShow_OnChecked" Content="图表 1" IsChecked="True"/>
            <CheckBox x:Name="chbChart2" Margin="10,0,0,0" Checked="ChartShow_OnChecked" Unchecked="ChartShow_OnChecked" Content="图表 2" IsChecked="True"/>
            <CheckBox x:Name="chbChart3" Margin="10,0,0,0" Checked="ChartShow_OnChecked" Unchecked="ChartShow_OnChecked" Content="图表 3" IsChecked="True"/>
            <CheckBox x:Name="chbChart4" Margin="10,0,0,0" Checked="ChartShow_OnChecked" Unchecked="ChartShow_OnChecked" Content="图表 4" IsChecked="True"/>
        </StackPanel>

        <!-- 动态布局的 Grid -->
        <Grid x:Name="MainGrid" Margin="10,60,10,10">
            <Border x:Name="chart1" Background="LightBlue" Visibility="Visible" BorderBrush="Black" BorderThickness="1" />
            <Border x:Name="chart2" Background="LightCoral" Visibility="Visible" BorderBrush="Black" BorderThickness="1" />
            <Border x:Name="chart3" Background="LightGreen" Visibility="Visible" BorderBrush="Black" BorderThickness="1" />
            <Border x:Name="chart4" Background="LightGoldenrodYellow" Visibility="Visible" BorderBrush="Black" BorderThickness="1" />
        </Grid>
    </Grid>
</Window>
C# 代码

接下来,我们在 C# 代码中根据用户的选择动态更新布局。关键是 ChartShow_OnChecked 方法,它根据当前选中的 CheckBox 控制图表的可见性,并动态调整 Grid 的行列定义。

csharp 复制代码
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        UpdateChartLayout();
    }

    // 控制图表显示的事件
    private void ChartShow_OnChecked(object sender, RoutedEventArgs e)
    {
        // 确保至少有一个图表被选中
        bool isAnyChecked = chbChart1.IsChecked == true ||
                            chbChart2.IsChecked == true ||
                            chbChart3.IsChecked == true ||
                            chbChart4.IsChecked == true;

        // 如果没有任何图表选中,恢复当前选中的图表
        if (!isAnyChecked && sender is CheckBox currentCheckBox)
        {
            currentCheckBox.IsChecked = true;
            MessageBox.Show("至少需要选中一个图表!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
            return;
        }

        // 控制对应图表的显示和隐藏
        chart1.Visibility = chbChart1.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;
        chart2.Visibility = chbChart2.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;
        chart3.Visibility = chbChart3.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;
        chart4.Visibility = chbChart4.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;

        // 更新布局
        UpdateChartLayout();
    }

    // 更新图表的布局
    private void UpdateChartLayout()
    {
        // 获取当前显示的图表
        var visibleCharts = new[] { chart1, chart2, chart3, chart4 }
            .Where(chart => chart.Visibility == Visibility.Visible)
            .ToList();

        // 清空现有的布局
        MainGrid.RowDefinitions.Clear();
        MainGrid.ColumnDefinitions.Clear();

        // 设置默认的布局
        foreach (var chart in visibleCharts)
        {
            Grid.SetRow(chart, 0);
            Grid.SetColumn(chart, 0);
            Grid.SetColumnSpan(chart, 1);
        }

        // 根据图表数量进行不同布局
        switch (visibleCharts.Count)
        {
            case 1:
                // 单个图表,铺满整个区域
                MainGrid.RowDefinitions.Add(new RowDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());
                Grid.SetRow(visibleCharts[0], 0);
                Grid.SetColumn(visibleCharts[0], 0);
                break;

            case 2:
                // 两个图表,水平排列
                MainGrid.RowDefinitions.Add(new RowDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());
                Grid.SetRow(visibleCharts[0], 0);
                Grid.SetColumn(visibleCharts[0], 0);
                Grid.SetRow(visibleCharts[1], 0);
                Grid.SetColumn(visibleCharts[1], 1);
                break;

            case 3:
                // 三个图表,上方两个,下面一个铺满
                MainGrid.RowDefinitions.Add(new RowDefinition());
                MainGrid.RowDefinitions.Add(new RowDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());

                Grid.SetRow(visibleCharts[0], 0);
                Grid.SetColumn(visibleCharts[0], 0);
                Grid.SetRow(visibleCharts[1], 0);
                Grid.SetColumn(visibleCharts[1], 1);

                Grid.SetRow(visibleCharts[2], 1);
                Grid.SetColumn(visibleCharts[2], 0);
                Grid.SetColumnSpan(visibleCharts[2], 2); // 跨两列
                break;

            case 4:
                // 四个图表,标准两行两列
                MainGrid.RowDefinitions.Add(new RowDefinition());
                MainGrid.RowDefinitions.Add(new RowDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition());

                for (int i = 0; i < visibleCharts.Count; i++)
                {
                    Grid.SetRow(visibleCharts[i], i / 2);
                    Grid.SetColumn(visibleCharts[i], i % 2);
                }
                break;
        }
    }
}
相关推荐
zzyzxb12 小时前
WPF 中隧道事件和冒泡事件
wpf
闲人编程12 小时前
API限流、鉴权与监控
分布式·python·wpf·限流·集群·令牌·codecapsule
TA远方14 小时前
【WPF】桌面程序使用谷歌浏览器内核CefSharp控件详解
wpf·浏览器·chromium·控件·cefsharp·cefsharp.wpf
Macbethad1 天前
工业设备数据采集主站程序技术方案
wpf
关关长语1 天前
HandyControl 3.5.x 版本 ListViewItem不显示问题
windows·wpf
Macbethad1 天前
工业设备维护程序技术方案
wpf
Macbethad1 天前
工业设备配方管理系统技术方案
wpf
喵叔哟1 天前
7.日志系统深入
wpf
清风徐来Groot2 天前
WPF布局之Grid
wpf
清风徐来Groot2 天前
WPF布局之WrapPanel
wpf