G.Williams G.Williams - 5 months ago 69
Vb.net Question

VB.NET WPF ComboBox SelectedValuePath SelectionChanged

I'm new to WPF and the concept of databinding, and I am in the process of teaching myself (with this application and a few books).

I've tried searching, but there are lots of questions (and answers) about how to bind it, but not how to reference/use the selected Item from the SelectedValue and SelectedValuePath:

Overview:
I'm populating a ComboBox on window_loaded as below:

Private db As New Pluto_DBDataContext()
Private OrganisationTypeView As BindingListCollectionView

Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
LoadOrganisationType()
End Sub

Private Sub LoadOrganisationType()
Dim OrganisationTypeList = From EntOrgs In db.t_EntityOrgs
Join EntType In db.t_EntityTypes On EntType.ID Equals EntOrgs.FK_EntityType_ID
Order By EntOrgs.OrganisationType
Where EntOrgs.DateTime_To Is Nothing AndAlso EntType.DateTime_To Is Nothing _
AndAlso ((Not bolIndividualEntityType) And EntType.EntityType <> "Individual")
Select EntOrgs.OrganisationType, EntOrgs.ID

OrganisationType_ComboBox.DataContext = OrganisationTypeList
Me.OrganisationTypeView = CType(CollectionViewSource.GetDefaultView(OrganisationType_ComboBox.DataContext), BindingListCollectionView)
End Sub


XAML:

<ComboBox x:Name="OrganisationType_ComboBox" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding}" SelectedValue="{Binding OrganisationType}" SelectedValuePath="ID" DisplayMemberPath="OrganisationType"/>


ComboBox_SelectionChanged:
I then use the selected OrganisationType to filter a ListView of clients as below (Note there are other controls that also trigger RefreshOrganisationClientList()).

This is where my problem lies. How do I get the selected value AND/OR the ID (SelectedValuePath) for that selection.

Private Sub OrganisationType_ComboBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles OrganisationType_ComboBox.SelectionChanged
If OrganisationType_ComboBox.SelectedItem IsNot Nothing Then
RefreshOrganisationClientList()
End If
End Sub

Private Sub RefreshOrganisationClientList()
Dim sOrgType As String
Dim guOrgType_ID As Guid
Dim sOrganisationName As String
Dim sPostCode As String
Dim sOccupation As String

If OrganisationType_ComboBox.SelectedItem Is Nothing Then
sOrgType = Nothing
Else
'*****PROBLEM HERE*****
sOrgType = OrganisationType_ComboBox.SelectedItem.index(1).ToString
guOrgType_ID = OrganisationType_ComboBox.SelectedItem

'guOrgType_ID = Guid.Parse(OrganisationType_ComboBox.SelectedValuePath)

End If
MsgBox(sOrgType)
MsgBox(guOrgType_ID)

sOrganisationName = OrganisationName_TextBox.Text
sPostCode = OrgPostalCode_TextBox.Text
sOccupation = OrgOccupation_TextBox.Text

Dim FilteredClientList = From Clients In db.t_Clients
Join EntType In db.t_EntityTypes On EntType.ID Equals Clients.FK_EntityType_ID
Join EntOrgs In db.t_EntityOrgs On EntType.ID Equals EntOrgs.FK_EntityType_ID
Order By Clients.OrganisationName, Clients.Occupation, EntOrgs.OrganisationType
Where Clients.DateTime_To Is Nothing AndAlso EntType.DateTime_To Is Nothing AndAlso EntOrgs.DateTime_To Is Nothing _
AndAlso ((Not bolIndividualEntityType) And EntType.EntityType <> "Individual") _
AndAlso (If(sOrgType IsNot Nothing, EntOrgs.ID = guOrgType_ID, True)) _
AndAlso (If(sOrganisationName IsNot "", Clients.OrganisationName Like "*" & sOrganisationName & "*", True)) _
AndAlso (If(sPostCode IsNot "", Clients.Postal_Code Like "*" & sPostCode & "*", True)) _
AndAlso (If(sOccupation IsNot "", Clients.Occupation Like "*" & sOccupation & "*", True))
Select Clients.OrganisationName, EntOrgs.OrganisationType, Clients.Occupation, Clients.FormationDate, Clients.Postal_Code, Clients.ID

ExistingOrganisationClients_ListView.DataContext = FilteredClientList
Me.FilteredOrgansiationClientView = CType(CollectionViewSource.GetDefaultView(ExistingOrganisationClients_ListView.DataContext), BindingListCollectionView)
End Sub


I'm starting to think I'm misunderstanding the concept databinding itself and how to use the data selected from controls that are data bound, or I have overlooked something simple.

EDIT: I tried to post an image but since I'm new here, I'm unable to do so, so a description and an imgur link will have to do:
In both of the below "Partnerships" was selected from the ComboBox not "Charity". Charity is the first item in the list presented to the user.

Contents of SelectedValue:
SelectedValue Imgur Link

- OrganisationType_ComboBox.SelectedValue "Charity" Object {String}


Contents of SelectedItem:
SelectedItem Imgur Link

- OrganisationType_ComboBox.SelectedItem OrganisationType="Partnerships", ID={27775e86-0013-4b82-996f-f6c061e99b2f} Object {VB$AnonymousType_3(Of String, System.Guid)}
+ ID {27775e86-0013-4b82-996f-f6c061e99b2f} System.Guid
- OrganisationType "Partnerships" String


EDIT: For anyone that stumbles across this later on; the below is the updated to fix the above problem. Thanks again!:

XAML:

<ComboBox x:Name="OrganisationType_ComboBox" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding}" SelectedValuePath="ID" DisplayMemberPath="OrganisationType"/>


ComboBox_SelectionChanged:

Private Sub RefreshOrganisationClientList()
Dim sOrgType As String
Dim guOrgType_ID As Guid
Dim sOrganisationName As String
Dim sPostCode As String
Dim sOccupation As String

If OrganisationType_ComboBox.SelectedItem Is Nothing Then
guOrgType_ID = Nothing
Else
guOrgType_ID = OrganisationType_ComboBox.SelectedValue
End If

sOrganisationName = OrganisationName_TextBox.Text
sPostCode = OrgPostalCode_TextBox.Text
sOccupation = OrgOccupation_TextBox.Text

Dim FilteredClientList = From Clients In db.t_Clients
Join EntType In db.t_EntityTypes On EntType.ID Equals Clients.FK_EntityType_ID
Join EntOrgs In db.t_EntityOrgs On EntType.ID Equals EntOrgs.FK_EntityType_ID
Order By Clients.OrganisationName, Clients.Occupation, EntOrgs.OrganisationType
Where Clients.DateTime_To Is Nothing AndAlso EntType.DateTime_To Is Nothing AndAlso EntOrgs.DateTime_To Is Nothing _
AndAlso ((Not bolIndividualEntityType) And EntType.EntityType <> "Individual") _
AndAlso (If(guOrgType_ID <> Guid.Empty, EntOrgs.ID = guOrgType_ID, True)) _
AndAlso (If(sOrganisationName IsNot "", Clients.OrganisationName Like "*" & sOrganisationName & "*", True)) _
AndAlso (If(sPostCode IsNot "", Clients.Postal_Code Like "*" & sPostCode & "*", True)) _
AndAlso (If(sOccupation IsNot "", Clients.Occupation Like "*" & sOccupation & "*", True))
Select Clients.OrganisationName, EntOrgs.OrganisationType, Clients.Occupation, Clients.FormationDate, Clients.Postal_Code, Clients.ID

ExistingOrganisationClients_ListView.DataContext = FilteredClientList
Me.FilteredOrgansiationClientView = CType(CollectionViewSource.GetDefaultView(ExistingOrganisationClients_ListView.DataContext), BindingListCollectionView)
End Sub

Answer

Here, you populate your combobox with instances of an anonymous type:

Dim OrganisationTypeList = From EntOrgs In db.t_EntityOrgs
                           Join EntType In db.t_EntityTypes On EntType.ID Equals EntOrgs.FK_EntityType_ID
                           Order By EntOrgs.OrganisationType
                           Where EntOrgs.DateTime_To Is Nothing AndAlso EntType.DateTime_To Is Nothing _
                           AndAlso ((Not bolIndividualEntityType) And EntType.EntityType <> "Individual")
                           Select EntOrgs.OrganisationType, EntOrgs.ID

OrganisationType_ComboBox.DataContext = OrganisationTypeList

When the user selects something, ComboBox.SelectedItem will be an instance of that anonymous type. You'll need a couple lines of reflection code to get any property values out of it, because you can't cast it to anything.

Fortunately, you had the good sense to set SelectedValuePath="ID" on the combobox. If SelectedValuePath names a property that actually exists on the selected item, the ComboBox will do all that reflection work for you, get the value of that named property from the selected item, and stuff it in the SelectedValue property. In this case, that should be SelectedItem.ID.

Guid selectedID = (Guid)OrganisationType_ComboBox.SelectedValue;

I'm guessing here that EntOrgs.ID is of type Guid. If it isn't, substitute whatever type it actually is.

int selectedID = (int)OrganisationType_ComboBox.SelectedValue;

Or whatever.

Comments