Search code examples
c#wpfdatagrid

C# WPF DataGrid Header Style Not Updating after On Click event handling


I have a C# WPF project using a DataGrid to display a DataTable. The DataTable was populated by reading in a CSV file (unknown number of headers) and populating it using the CSVHelper nuget package.

using (FileStream? stream = fileInfo.OpenRead())
{ 
    using (StreamReader? reader = new(stream))
    using (CsvReader? csv = new(reader, csvConfiguration))
    {
        using CsvDataReader? dr = new(csv);
        dataTable.Load(dr);
    }
}

I am displaying this DataTable using the following XAML setup.

<DataGrid x:Name="DataGrid"
            ItemsSource="{Binding Data, UpdateSourceTrigger=PropertyChanged}"
            HorizontalScrollBarVisibility="Visible" 
            VerticalScrollBarVisibility="Visible"
            AlternatingRowBackground="AliceBlue"
            AlternationCount="2"
            CanUserSortColumns="False"
            AutoGeneratingColumn="Data_AutoGeneratingColumn"
            IsReadOnly="True"
            CanUserReorderColumns="False"
            Loaded="Data_Loaded"
          >

    <DataGrid.ColumnHeaderStyle>
        <Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="DataGridColumnHeader">
            <EventSetter Event="Click" Handler="DataGridColumnHeader_Click"/>
        </Style>
    </DataGrid.ColumnHeaderStyle>
</DataGrid>

I have added code to the Loaded Event for the DataGrid that cycles through all the DataGridColumn entries from DataGrid.Columns and will set their HeaderStyle depending on if they exist in a List<string> to either:

  1. SelectedHeaderStyle
  2. UnSelectedHeaderStyle
foreach (DataGridColumn column in grid.Columns)
{
    string headerText = column.Header.ToString();
    if (cSVConfigureContext.SelectedColumns.Contains(headerText))
    {
        column.HeaderStyle = selectedHeaderStyle;
    }
    else
    {
        column.HeaderStyle = notSelectedHeaderStyle;
    }
}

I am also handling the Click event for TargetType DataGridColumnHeader which will toggle the HeaderStyle between 1 and 2.

private void DataGridColumnHeader_Click(object sender, RoutedEventArgs e)
{
    var columnHeader = sender as DataGridColumnHeader;
    if (columnHeader != null)
    {
        string headerText = columnHeader.Content.ToString();
        if (cSVConfigureContext.SelectedColumns.Contains(headerText))
        {
           columnHeader.Style = notSelectedHeaderStyle;

           cSVConfigureContext.SelectedColumns.Remove(headerText);
        }
        else
        {
            columnHeader.Style = selectedHeaderStyle;
            cSVConfigureContext.SelectedColumns.Add(headerText);
        }
    }
    e.Handled = true;
}

Header Selected and unSelected Result

This part all seems to work. However, adding a "Reset Headers" button to return to a default set of selected columns, is where things are not working.

If I load the window with the DataGrid and press the Reset button (which runs the same code used in the Loaded event, it works fine. But if I first click on any header to switch its state, the style on the column header does not change. I see the change in the SelectedColumns list of strings but no visual update in the DataGrid until I close that window and re-open a new DataGrid. But I can still click headers to change their state.

I've spent a couple hours googling options for forcing a redraw of the column headers but so far no luck.

Any ideas why the Reset button doesn't work after a Click event?


Solution

  • Any ideas why the Reset button doesn't work after a Click event?

    The Style of the DataGridColumnHeader apparently overrides or take precedence over the HeaderStyle of the DataGrid.

    Setting the Style property of all DataGridColumnHeader elements to null before setting the HeaderStyle property of the DataGrid will probably fix your issue.