In my previous blog Windows 10 (including IoT) USB HID device identification was covered in detail. This included an app that takes the relevant IDs for an HID device and checks whether it is present on the system. Two of the IDs could be looked up via a menu as they come an HID Usage table. The menu data was loaded from a JSON (text) file and translated using Linq to a list that is the Xaml data source binding for the menu. This blog demonstrates the mechanism for loading JSON data from a text file into an Xaml ComboBox.




Where major functionality is included in MainPage class, I prefer to separate that functionality into a separate file as further Page partial class:

  1. Create a secondary file for MainPage  (MainPageJSON.cs)

This will contain all of the relevant JSON and Linq code including classes and then menu SelectionChanged event handler.

  • Add a new class file to the project, called MainPageJSON.cs
  • Clear the file contents
  • Partially mirror MianPage.cs into MainPageJSON.cs by copying  all of MainPage.cs upwards from the line:
    public sealed partial class MainPage : Page
  • Place open an closing braces below the last line (public sealed partial class MainPage : Page) in MainPageJSON.cs


A USB device is identified by its Vendor ID, Product ID, UsagePage ID and Usage ID. The first two IDs are OEM specific. A USB mouse from different manufacturers will have a Vendor ID that identifies the OEM and a Product ID belonging to that OEM. The two usage IDs are defined in USB.org tables and will be the same for, for example, all USB mice. The menu looks up the usage IDs from by presenting a list of device classes for the user to select.


  1. Add the HidDeviceClass and its list to MainPageJSON.cs as follows:
        // This list is used to populate cbDevType dropdown menu
        private List<HidDeviceClass> HidDeviceClasses;
public class HidDeviceClass { public HidDeviceClass(string usageName, ushort pageID, ushort usageID) { UsageName = usageName; PageID = pageID; UsageID = usageID; } public string UsageName { get; set; } public ushort PageID { get; set; } public ushort UsageID { get; set; } }

HidDeviceClasses is what will be bound to the menu. The UsageName will be what is displayed for user selection. The PageID and UsageID will be the required IDs for further processing. The menu items are in the image below (circled in red):

image

The menu displayed in the app.


The ComboBox menu Xaml code snippet is:



            <ComboBox x:Name="cbDevType" ItemsSource="{Binding}" 
HorizontalAlignment="Left" Height="47" Margin="493,33,0,0"
VerticalAlignment="Top" Width="134"
SelectionChanged="cbDevType_SelectionChanged" > <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Width="Auto" Height="Auto"> <TextBlock Text="{Binding UsageName}" /> <TextBlock Text="{Binding PageID}" Visibility="Collapsed"/> <TextBlock Text="{Binding UsageID}" Visibility="Collapsed" /> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
  • The ComboBox is named cbDevType
  • The UsageName from list objects is what is displayed
  • When a menu item is selected, cbDevType_SelectionChanged is called


The data is loaded from a (text) .json file and loaded as a JSON object. It is then translated using Linq to the  HidDeviceClasses list.
  1. JSON enable the app:

We need to get the NewtonSoft.json library via Nuget and include its using references.

  • In Visual Studio in the project, Menu—>Tools—>Nuget Package Manager—>Manage Nuget Packages for the Solution ..
  • Search for NewtonSoft.json if it isn’t showing, and install it for the app.  Close Nuget.
  • Add the following using references if not showing:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


Next we add a function that can be called in the MainPage constructor imediately after InitializeComponent();. This function will open the .json file as Json text stream reader, read the stream into a JSON object and then query it using Linq into the required list. The list is then made the data context for the ComboBox.


  1. Add the following function to MainPage in MainPageJSON.cs
        private void GetUagePageInfo()
        {
            using (StreamReader file = File.OpenText(".\\usagepage.json"))
            using (JsonTextReader reader = new JsonTextReader(file))
            {
                 JObject jObject = (JObject)JToken.ReadFrom(reader);

            }
}
  1. After the JObject line add the following Json to Linq code to get the list:
                var hidDeviceClasses =
                    from p in jObject["hidDeviceClasses"]
                    select new HidDeviceClass((string)p["UsageName"], (ushort)p["PageID"], (ushort)p["UsageID"]);
                HidDeviceClasses = hidDeviceClasses.ToList<HidDeviceClass>();
  1. Finally added the following code to bind the list, just before exiting the function
              cbDevType.DataContext = HidDeviceClasses


Now to implement the list event handler:

  1. Add the following event handler to MainPage class in MainPageJSON:
 
       private void cbDevType_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!(cbDevType.SelectedIndex == -1))
            {
                //Get the selected object and use the usage IDs
                HidDeviceClass seln = (HidDeviceClass)cbDevType.SelectedItem;
                tb_usagepageID.Text = "0x" + seln.PageID.ToString("00");
                tb_usageID.Text = "0x" + seln.UsageID.ToString("00");
            }
        }

Now to create the json data file:

JSON 101:

  • A JSON object is a Name followed by a colon separated Value (Name-Value pair), with the object enclosed in braces.
  • The value is either a simple value (integer, string etc) or an object.
  • The object can also be be an array of values or objects. Arrays are enclosed in square brackets.

The JSON object for this data is Named hidDeviceClasses and its Value is an array of  HidDeviceClass objects.

  1. Create the JSON file as follows:
  • Add a new text file to the project and call it usagpage.json
  • Set its properties to Content, Copy if Newer and Custom Tool and Custom Tool Namespace both blank.
  • Insert the following into the file:
{
    "hidDeviceClasses": 
}
  • Looking up the USB.org reference you could add more pages to the data.


Summary

This blog explains how to load an Xaml menu with static data from a JSON data (text) data file.