You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF DataGrid中实现类似Microsoft Access表的关联记录功能

在WPF DataGrid中实现类似Access的关联数据展开功能

要实现Microsoft Access中那种点击行左侧"+"展开关联数据的效果,你可以利用WPF DataGrid的RowDetailsTemplate结合自定义行头按钮完成,具体步骤如下:

1. 准备数据实体

定义包含子集合的主实体类,同时实现INotifyPropertyChanged接口确保UI响应属性变化:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Order : INotifyPropertyChanged
{
    private int _orderId;
    public int OrderId
    {
        get => _orderId;
        set { _orderId = value; OnPropertyChanged(); }
    }

    private string _customerName;
    public string CustomerName
    {
        get => _customerName;
        set { _customerName = value; OnPropertyChanged(); }
    }

    // 存储关联的子数据
    public ObservableCollection<OrderItem> OrderItems { get; set; } = new ObservableCollection<OrderItem>();

    private bool _isExpanded;
    // 控制行详情的展开/折叠状态
    public bool IsExpanded
    {
        get => _isExpanded;
        set { _isExpanded = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class OrderItem
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
}

2. 实现XAML布局

在DataGrid中配置自定义行头按钮、行详情模板,并绑定数据:

<Window x:Class="WpfDataGridExpandDemo.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:WpfDataGridExpandDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <!-- 转换器:将布尔值转为"+"/"-"符号 -->
        <local:BooleanToExpandSymbolConverter x:Key="BooleanToExpandSymbolConverter"/>
    </Window.Resources>
    <Grid>
        <DataGrid x:Name="OrderDataGrid" AutoGenerateColumns="False" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="订单ID" Binding="{Binding OrderId}" Width="100"/>
                <DataGridTextColumn Header="客户名称" Binding="{Binding CustomerName}" Width="200"/>
            </DataGrid.Columns>
            
            <!-- 自定义行头:添加展开/折叠按钮 -->
            <DataGrid.RowHeaderTemplate>
                <DataTemplate>
                    <Button Width="20" Height="20" Click="ExpandCollapseButton_Click"
                            Content="{Binding IsExpanded, Converter={StaticResource BooleanToExpandSymbolConverter}}">
                        <Button.Style>
                            <Style TargetType="Button">
                                <Setter Property="BorderThickness" Value="0"/>
                                <Setter Property="Background" Value="Transparent"/>
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Background" Value="#EEEEEE"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Button.Style>
                    </Button>
                </DataTemplate>
            </DataGrid.RowHeaderTemplate>
            
            <!-- 行详情模板:显示关联的子数据 -->
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <DataGrid ItemsSource="{Binding OrderItems}" AutoGenerateColumns="False" Margin="20,0,0,0">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="产品ID" Binding="{Binding ProductId}" Width="100"/>
                            <DataGridTextColumn Header="产品名称" Binding="{Binding ProductName}" Width="200"/>
                            <DataGridTextColumn Header="数量" Binding="{Binding Quantity}" Width="80"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
    </Grid>
</Window>

3. 实现转换器和后台逻辑

创建布尔值转符号的转换器,并处理按钮点击事件切换展开状态:

转换器代码

using System;
using System.Globalization;
using System.Windows.Data;

namespace WpfDataGridExpandDemo
{
    public class BooleanToExpandSymbolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (bool)value ? "-" : "+";
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (string)value == "-";
        }
    }
}

后台按钮点击事件

using System.Windows;
using System.Windows.Controls;

namespace WpfDataGridExpandDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // 初始化模拟数据
            LoadSampleData();
        }

        private void LoadSampleData()
        {
            var orders = new ObservableCollection<Order>
            {
                new Order
                {
                    OrderId = 1,
                    CustomerName = "张三",
                    OrderItems = new ObservableCollection<OrderItem>
                    {
                        new OrderItem { ProductId = 101, ProductName = "笔记本", Quantity = 2 },
                        new OrderItem { ProductId = 102, ProductName = "钢笔", Quantity = 5 }
                    }
                },
                new Order
                {
                    OrderId = 2,
                    CustomerName = "李四",
                    OrderItems = new ObservableCollection<OrderItem>
                    {
                        new OrderItem { ProductId = 201, ProductName = "鼠标", Quantity = 1 },
                        new OrderItem { ProductId = 202, ProductName = "键盘", Quantity = 1 }
                    }
                }
            };
            OrderDataGrid.ItemsSource = orders;
        }

        private void ExpandCollapseButton_Click(object sender, RoutedEventArgs e)
        {
            var button = sender as Button;
            var order = button.DataContext as Order;
            if (order == null) return;

            // 切换展开状态
            order.IsExpanded = !order.IsExpanded;
            // 更新行详情的可见性
            var row = OrderDataGrid.ItemContainerGenerator.ContainerFromItem(order) as DataGridRow;
            if (row != null)
            {
                row.DetailsVisibility = order.IsExpanded ? Visibility.Visible : Visibility.Collapsed;
            }
        }
    }
}

关键说明

  • RowDetailsTemplate是WPF DataGrid内置的行详情模板,用来承载关联的子数据表格。
  • 自定义行头按钮通过绑定IsExpanded属性控制显示"+"或"-",点击时切换状态并更新行详情可见性。
  • 实体类实现INotifyPropertyChanged是为了让UI实时响应IsExpanded属性的变化。

内容的提问来源于stack exchange,提问作者Alejoho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:12:47