WPF Binding to NVList type BindingExpression path error: 'Key' property not found on 'object'

WPF Binding to NVList type BindingExpression path error: 'Key' property not found on 'object'

Old forum URL: forums.lhotka.net/forums/t/7791.aspx


richardb posted on Thursday, October 15, 2009

I have a business object that has a list of primary qualification types.  In the UI, when a user selects a type, a sub list is shown.  Naturally, this sub list changes as the qualification type is altered.

I can get the UI to refresh the sub type combo by  putting some code-behind in the qualification combo change events, but I really want the business object to take control and so, have declared my sub list as follows;

QualificationTypeList is a NVList object.

Private Shared QualificationSubTypesProperty As PropertyInfo(Of QualificationSubTypeList) = RegisterProperty(New PropertyInfo(Of QualificationSubTypeList)("QualificationSubTypeList", "QualificationSubTypeList"))

Public ReadOnly Property QualificationSubTypes() As QualificationSubTypeList
Get
 
LoadProperty(Of QualificationSubTypeList)(QualificationSubTypesProperty, 
       LoadSubQualificationList(GetProperty(_primaryQualTypeIDProperty)))

   Return GetProperty(QualificationSubTypesProperty)
End Get
End Property

Private Function LoadSubQualificationList(ByVal qualificationTypeID As Integer) As QualificationSubTypeList
Return QualificationSubTypeList.GetList(qualificationTypeID)
End Function

When I try and bind in WPF the combobox to the BO property, I get this error.

System.Windows.Data Error: 39 : BindingExpression path error: 'Key' property not found on 'object' ''Char' (HashCode=5308497)'. BindingExpression:Path=Key; DataItem='Char' (HashCode=5308497); target element is 'ComboBox' (Name='cboQualSubType'); target property is 'NoTarget' (type 'Object')

My WPF Xaml is as follows.

<Label Grid.Row="1" Grid.Column="6">Sub Qualification Type</Label>

<ComboBox Grid.Row="1" Grid.Column="7" Name="cboQualSubType"

ItemsSource="{Binding ItemsSource="{Binding Source=QualificationSubTypes}"

DisplayMemberPath="Value"

SelectedValuePath="Key"

SelectedValue="{Binding Path=PrimarySubQualTypeID}"

Width="150"

IsEnabled="True"

/>

<csla:PropertyStatus Grid.Row="1" Grid.Column="8" DataContext="{Binding}" Property="PrimarySubQualTypeID"

Target="{Binding ElementName=cboQualSubType}" />

What am I doing wrong here?  I'm having a stupid day :-)

My workaround would be to create a Datasource for the SubQualificationTypes and have tyhe UI refresh the control supplying the primaryqualificationid as a factory parameter, but this means the UI is in charge and really the BO should be updating the sublist as and when the primary qualification ID changes.

Hope that's clear.  Thanks.

PS.

I'm beginning to like WPF, but this is probably because the efforts of Rocky and CSLA have seriously eased the pain I would have otherwised experience.

 

RockfordLhotka replied on Thursday, October 15, 2009

Can you resend the binding expression for your ItemsSource property? What shows up in your post looks really strange - and if it is accurate I bet that expression is the source of your problem.

richardb replied on Friday, October 16, 2009

Yes I think my cut and paste was wrong there.

My primary combo (which works fine) uses a CSLA datasource in the Xaml for this.

<ComboBox Grid.Row="0" Grid.Column="7" Name="cboQualType"

ItemsSource="{Binding Source={StaticResource QualificationTypeList}}"

DisplayMemberPath="Value"

SelectedValuePath="Key"

SelectedValue="{Binding Path=PrimaryQualTypeID}"

Width="150"

IsEnabled="True"

/>

<csla:PropertyStatus Grid.Row="0" Grid.Column="8" DataContext="{Binding}" Property="PrimaryQualTypeID"

Target="{Binding ElementName=cboQualType}" />

 

For the sub qual combo I'm trying to bind to a property on the business object that is returning a filtered list rather than have a CSLA datasource. 

<ComboBox Grid.Row="1" Grid.Column="7" Name="cboQualSubType"

ItemsSource="{Binding Source=QualificationSubTypes}"

DisplayMemberPath="Value"

SelectedValuePath="Key"

SelectedValue="{Binding Path=PrimarySubQualTypeID}"

Width="150"

IsEnabled="True"

/>

This is how I have declared the property.

#Region " Filtered Lists "

Private Shared QualificationSubTypesProperty As PropertyInfo(Of QualificationSubTypeList) = RegisterProperty(New PropertyInfo(Of QualificationSubTypeList)("QualificationSubTypeList", "QualificationSubTypeList"))

''' <Summary>

''' Gets the QualificationSubTypeList value.

''' </Summary>

Public ReadOnly Property QualificationSubTypes() As QualificationSubTypeList

Get

'If Not FieldManager.FieldExists(QualificationSubTypeListProperty) Then

LoadProperty(Of QualificationSubTypeList)(QualificationSubTypesProperty, LoadSubQualificationList(GetProperty(_primaryQualTypeIDProperty)))

'End If

Return GetProperty(QualificationSubTypesProperty)

End Get

End Property

Private Function LoadSubQualificationList(ByVal qualificationTypeID As Integer) As QualificationSubTypeList

Return QualificationSubTypeList.GetList(qualificationTypeID)

End Function

#End Region

 

And maybe the object should refresh the subqualtypelist as and when the primary id changes?  Like this?

 

Private Shared ReadOnly _primaryQualTypeIDProperty As PropertyInfo(Of Integer) = RegisterProperty(Of Integer)(Function(p As ProgrammeOfStudy) p.PrimaryQualTypeID)

Public Property PrimaryQualTypeID() As System.Nullable(Of Integer)

Get

Return GetProperty(_primaryQualTypeIDProperty)

End Get

Set(ByVal value As System.Nullable(Of Integer))

SetProperty(_primaryQualTypeIDProperty, value)

'Refresh the sub qual type list so it is filtered for this primary qual type.

LoadProperty(Of QualificationSubTypeList)(QualificationSubTypesProperty, LoadSubQualificationList(GetProperty(_primaryQualTypeIDProperty)))

End Set

End Property

Copyright (c) Marimer LLC