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

如何在WPF DataGrid中选择全部用户时自动添加对应列?

WPF DataGrid 动态生成用户工时列(单选/全选切换)

需求说明

开发一款支持用户添加的工时计算软件,工时窗口的ComboBox可选择单个用户或「全部用户」:

  • 选择单个用户时,DataGrid仅显示该用户的工时列
  • 选择「全部用户」时,DataGrid自动添加所有用户对应的工时列

当前使用的DataGrid XAML代码:

<DataGrid
    Name="DgEsportazione"
    AutoGenerateColumns="False"
    IsReadOnly="True"
    ItemsSource="{Binding OreDate, UpdateSourceTrigger=PropertyChanged}"
    BindingGroup="{Binding ListaUtenti}"
    Style="{StaticResource DataGridStyle1}">
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Key.DayOfWeek}" Value="Saturday">
                    <Setter Property="Background" Value="{StaticResource Background}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Key.DayOfWeek}" Value="Sunday">
                    <Setter Property="Background" Value="{StaticResource Background}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.ItemContainerStyle>
    <DataGrid.Columns>
        <DataGridTextColumn
            Width="*"
            MinWidth="100"
            Binding="{Binding Key, ConverterCulture='it-IT', StringFormat=dddd dd/MM}"
            Header="Date"
            IsReadOnly="True" />
        <DataGridTextColumn
            Width="*"
            MinWidth="100"
            Binding="{Binding Value}"
            Header="Working Hours"
            IsReadOnly="True" />
    </DataGrid.Columns>
</DataGrid>

解决方案

要实现动态列切换,需从数据模型调整和ViewModel动态管理列集合两方面入手:

1. 调整数据模型

原OreDate的字典结构仅能存储单用户工时,需改为支持多用户的自定义类:

public class DailyWorkHours : INotifyPropertyChanged
{
    private DateTime _date;
    public DateTime Date
    {
        get => _date;
        set { _date = value; OnPropertyChanged(); }
    }

    // 存储每个用户的工时,Key为用户标识,Value为工时数
    public Dictionary<string, double> UserHours { get; set; } = new Dictionary<string, double>();

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

ViewModel中对应的数据源更新为:

public ObservableCollection<DailyWorkHours> OreDate { get; set; } = new ObservableCollection<DailyWorkHours>();

2. ViewModel中管理动态列

在ViewModel中添加属性和方法,实现选中项变化时自动生成列:

// 所有用户列表
public ObservableCollection<string> ListaUtenti { get; set; } = new ObservableCollection<string>();

// 选中的用户(包含"全部用户"选项)
private string _selectedUser;
public string SelectedUser
{
    get => _selectedUser;
    set 
    { 
        _selectedUser = value; 
        OnPropertyChanged();
        GenerateWorkHoursColumns();
    }
}

// DataGrid的动态列集合
public ObservableCollection<DataGridColumn> WorkHoursColumns { get; set; } = new ObservableCollection<DataGridColumn>();

// 生成工时列的核心方法
private void GenerateWorkHoursColumns()
{
    WorkHoursColumns.Clear();

    // 添加固定的日期列
    var dateColumn = new DataGridTextColumn
    {
        Width = new DataGridLength(1, DataGridLengthUnitType.Star),
        MinWidth = 100,
        Binding = new Binding("Date") { ConverterCulture = new CultureInfo("it-IT"), StringFormat = "dddd dd/MM" },
        Header = "Date",
        IsReadOnly = true
    };
    WorkHoursColumns.Add(dateColumn);

    // 根据选中项生成对应工时列
    if (SelectedUser == "全部用户")
    {
        foreach (var user in ListaUtenti.Where(u => u != "全部用户"))
        {
            var hourColumn = new DataGridTextColumn
            {
                Width = new DataGridLength(1, DataGridLengthUnitType.Star),
                MinWidth = 100,
                Binding = new Binding($"UserHours[{user}]"),
                Header = user,
                IsReadOnly = true
            };
            WorkHoursColumns.Add(hourColumn);
        }
    }
    else
    {
        var hourColumn = new DataGridTextColumn
        {
            Width = new DataGridLength(1, DataGridLengthUnitType.Star),
            MinWidth = 100,
            Binding = new Binding($"UserHours[{SelectedUser}]"),
            Header = "Working Hours",
            IsReadOnly = true
        };
        WorkHoursColumns.Add(hourColumn);
    }
}

3. 修改XAML绑定

更新DataGrid的XAML,绑定动态列集合并保留原有行样式:

<DataGrid
    Name="DgEsportazione"
    AutoGenerateColumns="False"
    IsReadOnly="True"
    ItemsSource="{Binding OreDate, UpdateSourceTrigger=PropertyChanged}"
    Columns="{Binding WorkHoursColumns}"
    Style="{StaticResource DataGridStyle1}">
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Date.DayOfWeek}" Value="Saturday">
                    <Setter Property="Background" Value="{StaticResource Background}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Date.DayOfWeek}" Value="Sunday">
                    <Setter Property="Background" Value="{StaticResource Background}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.ItemContainerStyle>
</DataGrid>

4. 初始化ComboBox

在ViewModel构造函数中添加「全部用户」选项并设置默认选中:

public YourViewModel()
{
    ListaUtenti.Insert(0, "全部用户");
    SelectedUser = "全部用户";
}

关键说明

  • 利用ObservableCollection<DataGridColumn>实现列的动态增删,选中项变化时自动刷新列集合
  • 通过字典索引器UserHours[{user}]实现列与用户工时的绑定
  • 保留了原有的周末行背景样式,仅调整绑定路径适配新数据模型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:08:11