Search code examples
wpfentity-frameworkdata-bindingcomboboxtextblock

WPF Entity Framework Combobox (Data Binding to Foreign Key of Related Table) Display as TextBlock (SelectedValuePath Equivalent)


I'm creating a WPF data access layer that probably doesn't require full MVVM at this stage (but I might implement it).

I've successfully created a ComboBox that data binds to a foreign key value of a related table using a CollectionViewSource as the data source (See my XAML below, the combo box works fine but the TextBlock doesn't).

I only want to display the ComboBox as the cell editing template and use a TextBlock for displaying the data when it is not being edited. I can get the TextBlock to almost work (it displays data from the table related in the Foreign Key) but I can't find the equivalent property for "SelectedValuePath" so the TextBlock always displays the first value from the related table, rather than the value that corresponds to the ID in the Foreign Key field.

Is there a way (there must be) to get an equivalent behaviour from the TextBlock as I have in the ComboBox? Is there an equivalent property for SelectedValuePath?

The answer to this question would be hugely useful as there are some other fields I want to display in my data grid without providing the user any ability to edit but I still want to display a field from a related table rather than the Foreign Key ID.

Thanks so much in advance for your help and have a great day!

<CollectionViewSource x:Key="QGradeLookup"/>

                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock
                            Text="{Binding Source={StaticResource QGradeLookup}, Path=QGrade}"
                            >
                        </TextBlock>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>

                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox
                            IsEditable="False"
                            ItemsSource="{Binding Source={StaticResource QGradeLookup}}"
                            DisplayMemberPath="QGrade"
                            SelectedValuePath="ID"
                            SelectedValue="{Binding Path=OfficeQualityGradeID}"
                            IsSynchronizedWithCurrentItem="False"
                            >
                        </ComboBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>

            </DataGridTemplateColumn>

As requested here's the code for the item's source (thanks NIT):

Dim QGradeLookup As CollectionViewSource
Dim QGradeList = From q In OMRInterfaceEntities.OfficeQualityGrades
Dim QGsource = CType(Me.FindResource("QGradeLookup"), CollectionViewSource)
QGsource.Source = QGradeList.ToList()

I used Beth Massi's post as a template for the above - Beth Massi's Template

And here's the codebehind

Public Class WinPropertyDataEntry

Dim QGradeLookup As CollectionViewSource

Private Function GetOMRMarketsQuery(OMRInterfaceEntities As OMRInterfaceCustomCode.OMRInterfaceEntities) As System.Data.Objects.ObjectQuery(Of OMR.OMRInterfaceCustomCode.OMRMarket)
    Dim OMRMarketsQuery As System.Data.Objects.ObjectQuery(Of OMR.OMRInterfaceCustomCode.OMRMarket) = OMRInterfaceEntities.OMRMarkets
    'To explicitly load data, you may need to add Include methods like below:
    'OMRMarketsQuery = OMRMarketsQuery.Include("OMRMarkets.OMRMarketType").
    'For more information, please see http://go.microsoft.com/fwlink/?LinkId=157380
    'Update the query to include Properties data in OMRMarkets. You can modify this code as needed.
    OMRMarketsQuery = OMRMarketsQuery.Include("Properties")
    'Update the query to include OMRBuildingSurveys data in OMRMarkets. You can modify this code as needed.
    OMRMarketsQuery = OMRMarketsQuery.Include("Properties.OMRBuildingSurveys").Where("it.ID = 12")
    'Returns an ObjectQuery.
    Return OMRMarketsQuery
End Function

Private Sub Window_Loaded_1(sender As Object, e As RoutedEventArgs) Handles MyBase.Loaded
    Dim OMRInterfaceEntities As OMR.OMRInterfaceCustomCode.OMRInterfaceEntities = New OMR.OMRInterfaceCustomCode.OMRInterfaceEntities()
    'Load data into OMRMarkets. You can modify this code as needed.
    Dim OMRMarketsViewSource As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("OMRMarketsViewSource"), System.Windows.Data.CollectionViewSource)
    Dim OMRMarketsQuery As System.Data.Objects.ObjectQuery(Of OMR.OMRInterfaceCustomCode.OMRMarket) = Me.GetOMRMarketsQuery(OMRInterfaceEntities)
    OMRMarketsViewSource.Source = OMRMarketsQuery.Execute(System.Data.Objects.MergeOption.AppendOnly)

    Dim QGradeList = From q In OMRInterfaceEntities.OfficeQualityGrades
    Dim QGsource = CType(Me.FindResource("QGradeLookup"), CollectionViewSource)
    QGsource.Source = QGradeList.ToList()

End Sub

Solution

  • Okay, thanks so much Nit for your help. Your solution would absolutely work in a different scenario but each building survey has it's own unique Quality Grade. The answer is that I was referencing the object incorrectly. I was using the name of the column (OfficeQualityGradeID) Rather than the name of the object OfficeQualityGrade.

    The following code provides a text block for the display of Quality Grades and a Combo Box for editing Quality Grades:

                        <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock
                                Text="{Binding OfficeQualityGrade.QGrade}"
                                />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
    
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox
                                x:Name="QGradeSelector"
                                IsEditable="False"
                                ItemsSource="{Binding Source={StaticResource QGradeLookup}}"
                                DisplayMemberPath="QGrade"
                                SelectedValuePath="ID"
                                SelectedValue="{Binding Path=OfficeQualityGradeID}"
                                IsSynchronizedWithCurrentItem="False"
                                >
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>