Raya
Raya

Reputation: 148

Dynamically add a column in WPF DataGrid

I am working on an MVVM WPF DataGrid application. I have a DataGrid and a multiselect CheckBox dropdown menu above it. Whenever I select an option in the menu, I want to add a column in the DataGrid. Is there any way to do that?

enter image description here

The code behind the ComboBox Item Template looks like this:

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

Upvotes: 0

Views: 2733

Answers (2)

BionicCode
BionicCode

Reputation: 29028

This is a simple example how to use a DataTable as data source for a 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", "[email protected]");

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

Upvotes: 2

Creative Coder
Creative Coder

Reputation: 102

I have recently faced something similar in a C# uwp application. Here's what worked for me.


Firstly, I created a list to keep track of all checked checkboxes:

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

Then, I created the checkboxes and linked them to the same events like so (You probably have code for this part already):

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);
        }

For the "CheckBox_Checked" event I did the following:

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

And for the "CheckBox_Unchecked" event I did the following:

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

To add a new column to your datagrid, you can refer to this answer. There are a few nice strategies there that may work for you. Here's the highest voted one for your convenience:

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

Sorry if I've done something wrong here, this is my first time posting an answer so go easy on me :)

Upvotes: 1

Related Questions