Search code examples
wpfvb.netdata-binding

Complex WPF Combobox


I'm learning WPF and starting to practice proper DataBinding and need to build a list of printers installed on a computer (Local + Network) & group them appropriately according to the Local & Network booleans.

At the moment I'm doing the following on load:

VB:

Class MainWindow

Public Property printerlist As New ObservableCollection(Of String)

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded

    InitializeComponent()
    Me.DataContext = Me

    'WMI Stuff
    Dim objMS As System.Management.ManagementScope = New System.Management.ManagementScope(ManagementPath.DefaultPath)

    objMS.Connect()

    'Query Printers
    Dim objquery As SelectQuery = New SelectQuery("SELECT * FROM Win32_Printer")
    Dim objMOS As ManagementObjectSearcher = New ManagementObjectSearcher(objMS, objquery)
    Dim objMOC As System.Management.ManagementObjectCollection = objMOS.Get()

    For Each Printers As ManagementObject In objMOC
         If CBool(Printers("Local")) Then
            printerlist.Add(Printers("Name"))
        End If
        If CBool(Printers("Network")) Then
            printerlist.Add(Printers("Name"))
        End If
    Next

End Sub

XAML:

<ComboBox x:Name="Printer_Select" ItemsSource="{Binding Path=printerlist}"/>

This successfully displays the local printer list & sorts them by Local then Network.

I've built the more advanced Combobox below:

<ComboBox x:Name="Printer_Select" ItemsSource="{Binding Path=printerlist}">
    <ComboBox.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Type}"/>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </ComboBox.GroupStyle>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding DeviceName}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

My issue is i'm struggling to work out how to actually bind the individual values from the WMI query to subsequent values in the printerlist object.

Can someone explain how to do this using VB (I can find several C# examples but I'm not so au fait with translating between the languages in this manner) - I'm moving a number of WinForms programs to WPF and don't want to have to change the VB back-ends just yet.

All help appreciated.


Solution

  • My issue is i'm struggling to work out how to actually bind the individual values from the WMI query to subsequent values in the printerlist object.

    I am afraid you cannot bind to the the individual values of the ManagementObject directly as they aren't exposed using public properties.

    You could create your own type:

    Public Class YourType
        Public Property DeviceName As String
        '+ all other properties that you want to display...
    End Class
    

    ...and change the type of printerlist from ObservableCollection(Of String) to ObservableCollection(Of YourType) and then create YourType objects in the loop:

    For Each Printers As ManagementObject In objMOC
        printerlist.Add(New YourType With {.DeviceName = Printers("DeviceName")})
    Next