在 WPF DataGrid 中动态添加一列

Dynamically add a column in WPF DataGrid

我正在开发 MVVM WPF DataGrid 应用程序。我在其上方有一个 DataGrid 和一个 multiselect CheckBox 下拉菜单。每当我 select 菜单中的一个选项时,我想在 DataGrid 中添加一列。有什么办法吗?

ComboBox 项目模板背后的代码如下所示:

<ComboBox.ItemTemplate>
        <DataTemplate>
               <CheckBox
                     VerticalAlignment="Center"
                     ClickMode="Press"
                     Content="{Binding Position}"
                     IsChecked="{Binding IsSelected}" />
        </DataTemplate>
</ComboBox.ItemTemplate>

我最近在 C# uwp 应用程序中遇到了类似的问题。这是对我有用的。


首先,我创建了一个列表来跟踪所有选中的复选框:

private List<CheckBox> checkedCheckboxes = new List<CheckBox>();

然后,我创建了复选框并将它们链接到相同的事件,就像这样(您可能已经有了这部分的代码):

foreach (foo blah in random)
        {
            var checkbox = new CheckBox(); //creating new checkbox
            checkbox.Content = blah.name; //setting content
            checkbox.Name = $"chk_{blah.name}"; //naming it
            checkbox.Tag = "blah"; //adding the tag

            checkbox.Checked += CheckBox_Checked; //adding the checked event
            checkbox.Unchecked += CheckBox_Unchecked; //adding the unchecked event

            ClassCheckboxes.Add(checkbox);
        }

对于“CheckBox_Checked”事件,我执行了以下操作:

private void CheckBox_Checked(object sender, RoutedEventArgs e)
    {
        checkedCheckboxes.Add((CheckBox)sender);
        //Here you can put some code to update your datagrid
    }

对于“CheckBox_Unchecked”事件,我执行了以下操作:

private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
    {
        checkedCheckboxes.Remove((CheckBox)sender);
        //Here you can put some code to update your datagrid
    }

要向您的数据网格添加新列,您可以参考此answer。那里有一些不错的策略可能对您有用。为方便起见,这里是投票最高的:

DataGridTextColumn textColumn = new DataGridTextColumn(); 
textColumn.Header = "First Name"; 
textColumn.Binding = new Binding("FirstName"); 
dataGrid.Columns.Add(textColumn);

抱歉,如果我在这里做错了什么,这是我第一次发布答案,请放轻松 :)

这是一个如何使用 DataTable 作为 DataGrid 的数据源的简单示例。

ViewModel.cs

class VeiwModel : INotifyPropertyChanged
{
  // Let this property set() raise the INotifyPropertyChanged.PropertyChanged event
  // if its value/instance will change after instantiation
  public DataTable TableData { get; set; }

  public ViewModel()
  {
    var changedTable = new DataTable();
    AddColumn<int>("ID", changedTable);
    AddColumn<string>("Username", changedTable);
    AddColumn<string>("Mail", changedTable);

    // Add column values in order of their columns
    AddRow(changedTable, 1, "Me", "me@mail.com");

    // Update the DataGrid with changes
    this.TableData = changedTable; 
  }

  // Appends a new column. 
  // Use 'columnIndex' parameter to assign an other column index than the last
  private void AddColumn<TData>(string columnName, DataTable targetDataTable, int columnIndex = -1)
  {
    DataColumn newColumn = new DataColumn(columnName, typeof(TData));

    targetDataTable.Columns.Add(newColumn);
    if (columnIndex > -1)
    {
      newColumn.SetOrdinal(columnIndex);
    }

    int newColumnIndex = targetDataTable.Columns.IndexOf(newColumn);

    // Initialize existing rows with default value for the new column
    foreach (DataRow row in targetDataTable.Rows)
    {
      row[newColumnIndex] = default(TData);
    }
  }

  private void AddRow(DataTable targetDataTable, params object[] columnValues)
  {
    DataRow rowModelWithCurrentColumns = targetDataTable.NewRow();
    targetDataTable.Rows.Add(rowModelWithCurrentColumns);

    for (int columnIndex = 0; columnIndex < targetDataTable.Columns.Count; columnIndex++)
    {
      rowModelWithCurrentColumns[columnIndex] = columnValues[columnIndex];
    }
  }
}

MainWindow.xaml

<Window>
  <Window.DataContext>
    <ViewModel />
  </Window.DataContex>

  <DataGrid ItemsSource="{Binding TableData}" />
</Window>