Datagrid combobox selectionchanged event argument differ between two pc's

-1

Code:

private void updateSeconderyCombobox(object sender, SelectionChangedEventArgs e)
{
    object comboBox = null;

    if (sender is ComboBox) 
    {
        comboBox = (ComboBox)sender;
    } 
    else
    {
        comboBox = (TextBlock)sender;
    }

    DataGridRow row = (DataGridRow)dataGrid.ContainerFromElement((DependencyObject)comboBox);
    xyEntry newValues = null;

    if (row.Item != null)
    {
        newValues = (xyEntry)row.Item;
    }
    else 
    {
        return;
    }

    Factors fs = new Factors();
    List<Factor> list = fs.getFactors();
    Factor f = list.Find(x => x.Category == newValues.Category);
    newValues.FactorX = Convert.ToString(f.FactorXvalue);
    newValues.FactorY = Convert.ToString(f.FactorYvalue);

    newValues.SizeChoices = AddSeconderyCombobox(newValues.Category);
            
    row.Item = null;
    row.Item = newValues;
}

XAML:

<DataGrid SelectionUnit="FullRow" x:Name="dataGrid" Margin="10,110,162,15" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" AutoGenerateColumns="False" CanUserAddRows="False" CanUserReorderColumns="False">
    <DataGrid.Columns>

        <DataGridTextColumn Header="X Coord" Binding="{Binding xCoord}" IsReadOnly="True" Width="*" />
        <DataGridTextColumn Header="Y Coord" Binding="{Binding yCoord}" IsReadOnly="True" Width="*"/>
        <DataGridTextColumn Header="Rotation" Binding="{Binding Rotation}" IsReadOnly="True" Width="*"/>
        <DataGridTextColumn Header="RefDes" Binding="{Binding RefDes}" IsReadOnly="True" Width="*"/>
        <DataGridTextColumn Header="P/N" Binding="{Binding Number}" IsReadOnly="True" Width="*"/>
        <DataGridTextColumn Header="Package" Binding="{Binding Package}" IsReadOnly="True" Width="*"/>
        <DataGridTextColumn Header="FactorX %" Binding="{Binding FactorX}" IsReadOnly="False" Width="*"/>
        <DataGridTextColumn Header="FactorY %" Binding="{Binding FactorY}" IsReadOnly="False" Width="*"/>
        <DataGridCheckBoxColumn Header="Use factors" Binding="{Binding UseFactors}" IsReadOnly="False" Width="*"/>
            <DataGridTemplateColumn Header="Category" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Grid>
                            <ComboBox SelectedValue="{Binding Category, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding CategoryChoices}" SelectionChanged="updateSeconderyCombobox" >
                                <ComboBox.Style>
                                    <Style TargetType="ComboBox">
                                        <Setter Property="Visibility" Value="Hidden"/>
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Path=IsSelected}"
                                             Value="True">
                                                    <Setter Property="Visibility" Value="Visible" />
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </ComboBox.Style>
                                </ComboBox>
                                <TextBlock Text="{Binding Category}" >
                                    <TextBlock.Style>
                                        <Style TargetType="TextBlock">
                                            <Setter Property="Visibility" Value="Visible"/>
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Path=IsSelected}"
                                             Value="True">
                                                    <Setter Property="Visibility" Value="Hidden" />
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </TextBlock.Style>
                                </TextBlock>
                            </Grid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Size" Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <ComboBox SelectedValue="{Binding Size, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding SizeChoices}">
                                    <ComboBox.Style>
                                        <Style TargetType="ComboBox">
                                            <Setter Property="Visibility" Value="Hidden"/>
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Path=IsSelected}"
                                             Value="True">
                                                    <Setter Property="Visibility" Value="Visible" />
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </ComboBox.Style>
                                </ComboBox>
                                <TextBlock Text="{Binding Size}">
                                    <TextBlock.Style>
                                        <Style TargetType="TextBlock">
                                            <Setter Property="Visibility" Value="Visible"/>
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Path=IsSelected}"
                                             Value="True">
                                           <Setter Property="Visibility" Value="Hidden" />
                                       </DataTrigger>
                                   </Style.Triggers>
                               </Style>
                           </TextBlock.Style>
                       </TextBlock>
                   </Grid>
               </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object. Source=IsoEasy StackTrace: at IsoEasy.Windows.Link_parts.updateSeconderyCombobox(Object sender, SelectionChangedEventArgs e) at System.Windows.Controls.SelectionChangedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e) at System.Windows.Controls.ComboBox.OnSelectionChanged(SelectionChangedEventArgs e)

......

What occurs: Each row of the Datagrid contains 2 comboboxes. The first combobox is a static list of 6 categories, the second combobox get's populated depending on what category is selected. This works fine on 99% of the PC's I've tested. However, I have one PC where this gives a problem. The error occurs on:

DataGridRow row = (DataGridRow)dataGrid.ContainerFromElement((DependencyObject)comboBox);
xyEntry newValues = null;

if (row.Item != null){
    newValues = (xyEntry)row.Item;
}
else {
    return;
}

In the situation where this works, I see that the sender parameter contains the static list for the first combobox. But in this one case where this doesn't work the sender seems to be an empty combobox. This results in the fact that "row" variable gets set as null and I get a System.NullReferenceException when I check the items of this variable in the if statement.

What I tried:

  • First of all, I made sure the correct .Net version was installed. This had no effect.
  • I tried a hotfix by trying to set the itemsource of the sender after casting it to the correct data type, but this also throws a NullReferenceException.
  • The same windows versions are running on both machines
c#
wpf
combobox
datagrid
asked on Stack Overflow Aug 4, 2020 by T Jasinski • edited Aug 4, 2020 by T Jasinski

2 Answers

1

I think I had a similar issue with NullReferenceException and adding DataGridRow row = new DataGridRow(); before assigning value to row solved this problem.

answered on Stack Overflow Aug 4, 2020 by Dojdyl
0

Check whether the ComboBox has been loaded before you try to do anything. You should also avoid casting to anything else than a FrameworkElement:

private void updateSeconderyCombobox(object sender, SelectionChangedEventArgs e)
{
    FrameworkElement comboBox = sender as FrameworkElement;
    if (comboBox == null || !comboBox.IsLoaded)
        return;

    DataGridRow row = (DataGridRow)dataGrid.ContainerFromElement(comboBox);
    ...
}
answered on Stack Overflow Aug 4, 2020 by mm8

User contributions licensed under CC BY-SA 3.0