Turn your old Surface into into a large touchpad. As part 2, specify the buttons and app config via a Json Configuration file. This reworks a previous GitHub project.

 

Links

Index of Articles

Next: Text Output

Prev: The UI

Code Repository: (Github) djaus2/SurfPad

 

Other GitHub project: IotAzureSensors .. The IoTCoreMenu project within.

 

In the previous article, we showed you how to create a UWP app that implements a touch pad as an array of buttons that demonstrates how to:

  • Create the Button as a rounded box as a UserControl
  • The Button supports multiple line text,
  • A Grid is constructed programmatically, determined by specified parameters,
  • Buttons are programmatically added to the Grid.
  • Button tapped events are passed back to the main app, identifying which button was pressed.

 

In that version of the app, a few buttons are specified in the app. In this version, a Json file is read and interpreted as app configuration data as well as a specification of the the buttons. Code from a previous GitHub project, as listed above, is reused here to implement this extra functionality.That app targets a RPI2 as a UWP app that gets sensor data over USB or Bluetooth from an Arduino device and writes it to an Azure Mobile Service. (Note that Azure Mobile Service is now deprecated). App buttons are specified in a Json file

 

In the SurfPad project a C# class file is added in a Helpers folder and a Json file is added in a data folder. The files are copied from the IoTCoreMenu project:

  1. The class file is copied from IoTCoreMenu project Helpers/menus.cs to Helpers\menus.cs in the SurfPad project.
  2. The json file is copied from the root of the IoTCoreMenu project menus.json to Data\menus.json in the SurfPad project.

The json file is set as content to be copied in the build and the class file is set to be built.

The Json File

        { "iWidth": 120 },
        { "iHeight": 100 },
        { "iSpace": 5 },
        { "iCornerRadius": 10 },
        { "iRows": 6 },
        { "iColumns": 5 },

These lines as above were inserted as lines 9 to 14  in the json file. They can then be read in the app MainPage  constructor. The MainMenu items in the json file is reduced to six items as iRows is set to 6.

 

The structure of the json file is at the top level an array of objects:

image

 

The first object , ElementConfig is an array of app level configuration parameters such as the number of rows and columns. These are colon separated name value pairs:

image

Comment items are ignored.

 

The MainMenu items each represent a row in the grid of buttons; each item in the row being a button’s text.

image

 

The Class File

The Namespace for the class is set to the SurfPad Namespace, ie SurfPad.

The interface for the Commands class in the added class file is:

    public interface ICommands
    {
        bool Enabled { get; set; }
        Point idTag { get; set; }
        string menu { get; set; }
        string name { get; set; }
    }
  • idTag of type Point allows for the row and column of the button to be specified
  • Enabled is a property that was added for this app to the Commands class. The IoTCoreMenu  app inserts a TextBlock if the command name has an underscore prefix and a TextBox if the prefix is an equals sign. For  this app we will implement the TextBlock by setting the Button in the UserControl to disabled, remebering that its content is a TextBlock. We will ignore the TextBox option for now.
  • menu is the displayed text for each button.

So when the Json file is loaded with the “MainMenu” parameter, the metainformation for the buttons is loaded and can be used with the AddMyUserControl1() method. The following method DoCommands() loads the config and button meta info:

        List<Commands> MainMenu;
        private void DoCommands()
        {
            GetCommands("ElementConfig");
            //Following settings are mandatory
            bool res = Commands.CheckKeys();
            //Next two are optional settings
            ////bool res2 = Commands.CheckComportIdSettingExists();
            ////res2 = Commands.CheckcIfComportConnectDeviceNoKeySettingExists();
            GetCommands("MainMenu");
            MainMenu = Commands.GetMenu("MainMenu");
        }

This is called for the  InitTheGrid() call so that the config data can be used for the grid.

An example of the use of the config data is:

int iCornerRadius = Commands.ElementConfigInt["iCornerRadius"];

The app configuration item types are specified in their names:

  • i means integer type
  • c means char type
  • s means string type

There is a dictionary for each data type in which the configurations are stored as name-value pairs:

        public static void Init()
        {
            Commands.Sensors = new string[0];
            Commands.CommandActions = new string[0];
            Commands.CommandsList = new List<Commands>();
            Commands.ElementConfigInt = new Dictionary<string, int>();
            Commands.ElementConfigCh = new Dictionary<string, char>();
            Commands.ElementConfigStr = new Dictionary<string, string>();
        }

The MainPage constructor in the app is therefore modified to:

        public MainPage()
        {
            this.InitializeComponent();

            //Brush red = new SolidColorBrush(Colors.Red);
            //AddMyUserControl1( 0, 0,"arc1", "First", red,123,50,1,2);
            //AddMyUserControl1(1, 1, "arc2", "Second", null, 124, 5, 2);
            //AddMyUserControl1(2, 2, "The quick brown fox jumps over the lazy dog",  "Third");

            DoCommands();

            int iCornerRadius = Commands.ElementConfigInt["iCornerRadius"];

            InitTheGrid(Commands.ElementConfigInt["iRows"], Commands.ElementConfigInt["iColumns"],
                Commands.ElementConfigInt["iHeight"], Commands.ElementConfigInt["iWidth"], 
                Commands.ElementConfigInt["iSpace"]);
            foreach (var menuItem in MainMenu)
            {
                AddMyUserControl1(menuItem.idTag.Row, menuItem.idTag.Col, menuItem.name,"",
                    null,-1,iCornerRadius);
            }

            uc.MyUserControl1.ButtonTapped += MainPage_ButtonTapped1;

        }

 

Conclusion

The use of a json file to load app parameters, specifically for an XAML grid is demonstrated. Also button text is also loaded form the json file as a two dimensional array to be so placed as button text in the grid.

image

The running app

 

Conclusion

This article demonstrates how to specify app metadata in a Json file, how to load it and store in a dictionary and how to use it in configuring an XAML grid in code behind. It similarly demonstrates the specification of of the RoundeBbox button content..


Next: Add a Text control to display events