0
votes

Currently I have a TabControl with several TabItems. Each TabItem has a DataGrid inside. I wanted to format these DataGrids (cell colors, column widths, etc) all at once but I found I can't because all the DataGrids from the hidden tabs would return null properties. In this case, I tried to make a work around where I would select programmatically (or manually with the mouse) the tabs before formatting the DataGrid. But now I'm up against a "strange" behavior:

    private void LeftTabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Console.WriteLine(LeftTabs.SelectedIndex);
    var currentDataGrid = (DataGrid)LeftTabs.SelectedContent;
    Console.WriteLine(currentDataGrid.Name);
}

The selected index returns the correct tab index, but the content it's not updated. Let's say Tab 1 is selected and then I click on Tab 2. It returns me the Tab 2 index and the Tab 1 DataGrid name.

This behavior prevents me from editing the select tab's DataGrid because even if I try to access it directly by it's object, all the properties return null.

This is the TabControl, item and DataGrids XAML code:

<TabControl Name="LeftTabs" Margin="0,0,0,0"  Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionChanged="LeftTabs_SelectionChanged">
        <TabItem>
            <TabItem.Header>Conditions</TabItem.Header>
            <DataGrid x:Name="DataGrid_Conditions" SelectedCellsChanged="DataGrid_Conditions_SelectedCellsChanged" ColumnWidth="80" ItemsSource="{Binding}" HorizontalAlignment="Stretch"   VerticalAlignment="Top" SelectionChanged="ConditionsSelected" />
        </TabItem>
        <TabItem>
            <TabItem.Header>Signals</TabItem.Header>
            <DataGrid x:Name="DataGrid_Signals" ColumnWidth="80" ItemsSource="{Binding}" HorizontalAlignment="Stretch"  VerticalAlignment="Top" SelectionChanged="SignalsSelected" />
        </TabItem>
    </TabControl>

EDIT: To be more clear I'll minimize the scenario. TabItem1 - Has DataGrid_Conditions inside; TabItem2 - Has DataGrid_Signals inside.

Here is another code that I try to run when I manually or programmatically select a tab:

DataGridRow Row = (DataGridRow)DataGrid_Signals.ItemContainerGenerator.ContainerFromIndex(ID);

What happens is, If I click on tab2 this code doesn't for tab2's Grid. Instead it works for the previous tab(1) Grid. The LeftTabs.SelectedContent is the only property not being updated.

2

2 Answers

1
votes

I can't seem to reproduce your issue. "DataGrid_Signals" should be printed out when you selecte the second tab. You may also get a reference to the currently selected TabItem from the SelectionChangedEventArgs:

private void LeftTabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Debug.WriteLine(LeftTabs.SelectedIndex);
    TabItem tabItem = e.AddedItems[0] as TabItem;
    var currentDataGrid = (DataGrid)tabItem.Content;
    Debug.WriteLine(currentDataGrid.Name);
}

In this example despite it indeed printing "DataGrid_Signals" when I try to get anything from the grid's object, it just comes null as it was in a hidden.

This is because it has not yet been loaded. You can force it to render by measure and arrange it:

private void LeftTabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (IsLoaded)
    {
        TabItem tabItem = e.AddedItems[0] as TabItem;
        var currentDataGrid = (DataGrid)tabItem.Content;
        currentDataGrid.Measure(new Size(currentDataGrid.ActualWidth, currentDataGrid.ActualHeight));
        currentDataGrid.Arrange(new Rect(0, 0, currentDataGrid.ActualWidth, currentDataGrid.ActualHeight));
        //...
    }
}
0
votes

This is a bug, fixed in .NET 4.7.1 but quirked so that apps targeting 4.7 or below still get the old behavior. See the breaking change announcement for details.