Turn your old Surface into into a large touchpad. As part 3, add a Text Output control to the UI that can note which button is pressed along with (later on) output from the remote app.



Index of Articles

Next: SurfPad States

Prev: Json Configuration

Code Repository: (Github) djaus2/SurfPad


In the previous article we showed you how to load app metadata and button specifications from a Json file and use these values in configuring the button’s layout. In this article we add a a ListView to the UI to list button presses. Later on it will record messages from the remote app.


Requirement: Add a scrolling text control to the right of the buttons’ grid. As items are added to the list, they appear at the top with previous items scrolling downwards.  Make it the same height as the grid and a constant number of grid column widths (n) wide.

Implementation: Implement it as an XAM  ListView. Make it part of the grid appending n columns to the grid, set the control’s location in the grid to (0,Y) where Y is the button grid columns (the grid is now y+n columns wide) set the control’s ColumnSpan to n and its RowSpan to X where X is the number of button rows.

(1) Add the 3 last lines in what follows to the constants at the top of the MainPage code behind page (MainPage.xaml.cs)

        const int DefaultCellWidth= 120;
        const int DefaultCellHeight = 120;
        const int DefaultCellSpacing = 10;
        const int TextColSpan = 2; //Number of columns that the text control spans
        Brush Black = new SolidColorBrush(Colors.Black); //The text control border color
        Brush White = new SolidColorBrush(Colors.White); //The text control border background

(2) In the same page in InitTheGrid()

      (i) Modify the for j loop by extending its upper limit by TextColSpan as follows (adds TextColSpan columns to the grid)

            for (int j = 0; j < y+ TextColSpan; j++)
                ColumnDefinition cd2 = new ColumnDefinition();
                cd2.Width = new GridLength((double)Width);

     (ii) Create a new border bdr  in that code behind, add it to the grid and set it to span those extra columns top to bottom:

            var bdr =
                new Border
                    BorderThickness = new Thickness(1),
                    BorderBrush = Black,            
                    Background = White,
                    Padding = new Thickness(0),
                    CornerRadius = new CornerRadius(5)
            TheGrid.Children.Add(bdr );
            Grid.SetColumn(bdr , y);
            Grid.SetRow(bdr , 0);
            Grid.SetColumnSpan(bdr , TextColSpan);
            Grid.SetRowSpan(bdr , y+1);

     (ii) Create a ListView listView1  and insert it within the border bldr, (i.e. set it as bldr’s Child):

            listView1  = new ListView()
                IsEnabled = false,    /Disabled so items can’t be interacted with in teh list           
            bdr .Child = listView1  ;

(3) In the Button_Tapped event handler in MainPage, insert the sender (name) at the top of the ListView

        private void MainPage_ButtonTapped1(string sender, int args)
            string name = sender;
            int id = args;
            listView1.Items.Insert(0, name);


Need to modify the UserControl code behind a little. When setting TextBlock Text property (which is within the border) it is only writeable, not readable. Need to add a get() to the Text property. The value is “buried” a little as its a property of the TextBlock not the control when written. We could look at the Child property of the Border, cast it to a TextBlock then get the Text property of that. Its simpler though just to add a field (string text), set that in teh control’s property set and read it back in the property get():

(4) Modify the UserControl’s Text property to (changes in blue);

        private string text;
        //Enable wrapped text on button
        public string Text {
            set { TheText.Content =
                    new TextBlock
                        Text = value,
                        TextWrapping = TextWrapping.Wrap,
                        TextAlignment = TextAlignment.Center,
                text = value;
                return text;

(5) Finally, modify the control’s Tapped event handler  to return the control’s Text property

        private void TheText_Tapped(object sender, TappedRoutedEventArgs e)
            if (ButtonTapped != null)
                ButtonTapped(this.Text, this.Id);


The running app with the added ListView on right (recording button presses)



This article demonstrates how to add a a ListView to an XAML grid as code behind such that it spans the grid where the grid dimensions are unknown at design time. It also demonstrates how to add items at the top of the list.

Next: Remote app communications