DataGridComboBoxColumn binding issues in WPF MVVM application

508 Views Asked by At

I have a custom WPF MVVM (Prism) application I'm developing and am having some trouble with ComboBox bindings within a DataGrid. I have seen others with similar problems, but nothing quite the same and I cannot get any of the answers to work 100% for my situation.

For this particular view, I am representing a parent-child relationship. When displaying the form, I am displaying the parent info on top in a basic Grid and those bindings work fine. Below that is a DataGrid with 1:many items related to that parent record. It's pretty simple - just a TextBox representing Display Order, then a ComboBox holding a Statistic Type value. The ComboBox is bound to an ObservableCollection and I can get it to display those values properly; however, I am not able to get it to select the correct value for the given record. I am able to display the correct value in a TextBox, so I know the values are correct, I just can't get the right bindings on the ComboBox.

Here's the pertinent code:

View:

<DataGrid AutoGenerateColumns="false" Name="DataGridStatistics" Width="900" 
          ItemsSource="{Binding Path=DspTemplateStats, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                  >
    <DataGrid.Columns>
        <DataGridTextColumn Header="Display Order" Width="100"
                            Binding="{Binding Path=DisplayOrder, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
        <!-- This is where the issue is.  It is displaying the StatisticTypeName properly in the combobox, but it is not connecting the StatisticId
        from the DspTemplateStats collection to the StatisticTypes collection -->
        <DataGridComboBoxColumn Header="Statistic Type 2"
                                SelectedValueBinding="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.StatisticId}"
                                SelectedValuePath="StatisticId"
                                DisplayMemberPath="StatisticTypeName"
                                >
             <DataGridComboBoxColumn.ElementStyle>
                 <Style TargetType="ComboBox">
                     <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.StatisticTypes}"/>
                 </Style>
             </DataGridComboBoxColumn.ElementStyle>
             <DataGridComboBoxColumn.EditingElementStyle>
                 <Style TargetType="ComboBox">
                     <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.StatisticTypes}"/>
                     </Style>
             </DataGridComboBoxColumn.EditingElementStyle>
         </DataGridComboBoxColumn>
         <!-- This is temporary to test the binding.  It displays the correct value -->
         <DataGridTextColumn Header="Statistic" Width="*" Binding="{Binding Path=StatisticTypeName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
     </DataGrid.Columns>
 </DataGrid>

ViewModel

// This is how DspTemplateStats is defined, populated from Stored Procedure
// I pass it the ProejctTemplateId and it retrieves all the Statistics associated with it
private ObservableCollection<ProjectTemplateStat> dspTemplateStats;
public ObservableCollection<ProjectTemplateStat> DspTemplateStats
{
    get { return dspTemplateStats; }
    set
    {
        dspTemplateStats = value;
        OnPropertyChanged("DspTemplateStats");
    }
}

// This is how StatisticTypes is defined, populated from Stored Procedure
// It pulls back all StatisticTypes defined in the database
private ObservableCollection<StatisticType> statisticTypes;
public ObservableCollection<StatisticType> StatisticTypes
{
    get { return statisticTypes; }
    set
    {
        statisticTypes = value;
        OnPropertyChanged("StatisticTypes");
    }
}

And the key Models

public class ProjectTemplateStat
{
    public int ProjectTemplateId { get; set; }
    public int TemplateStatId { get; set; }
    public int StatisticId { get; set; }
    public string TemplateName { get; set; }
    public string StatisticTypeName { get; set; }
    public int DisplayOrder { get; set; }
}

// The match should between StatisticType.StatisticTypeId and ProjectTemplateStat.StatisticId
public class StatisticType
{
    public int StatisticTypeId { get; set; }
    public int UOMId { get; set; }
    public string UOMValue { get; set; }
    public int DatatypeId { get; set; }
    ...
}

I feel like the issue is on the DataGridComboBoxColumn bindings, but cannot seem to figure out what I'm missing. Thanks for any insight.

1

There are 1 best solutions below

1
AnjumSKhan On BEST ANSWER

Property used for SelectedValueBinding would be a custom property(place-holder) to get the value chosen by the user. You are using same property for SelectedValuePath and SelectedValueBinding, which is meaningless.