Gotcha: custom Microsoft Band page shows only data in last added UI element
Today I finally nailed a very odd issue in the Microsoft Band SDK - or actually, my understanding thereof. For my current research project, I am building a custom UI on my Microsoft Band. I should contain two panels: one with a text, an icon and a button, and a second panel containing two texts. Details of how to setup up something like this, can be found in the band samples.
Building a Band UI is not for the faint hearted, it includes building the UI from code without any kind of designer. Filling those UI elements with a value then is a separate step, which contains quite a big gotcha that you cannot derive from the samples.
My Band UI creation code is like this:
private IEnumerable<PageLayout> BuildTileUi() { var bandUi = new List<PageLayout>(); var page1Elements = new List<PageElement> { new Icon {ElementId = IconId, Rect = new PageRect(60,10,24,24)}, new TextBlock {ElementId = TextTemperatureId, Rect = new PageRect(90, 10, 50, 40)}, new TextButton {ElementId = ButtonToggleFanId, Rect = new PageRect(10, 50, 220, 40), HorizontalAlignment = HorizontalAlignment.Center} }; var firstPanel = new FilledPanel(page1Elements) { Rect = new PageRect(0, 0, 240, 150) }; var page2Elements = new List<PageElement> { new TextBlock {ElementId = TextTimeId, Rect = new PageRect(10, 10, 220, 40)}, new TextBlock {ElementId = TextDateId, Rect = new PageRect(10, 58, 220, 40)} }; var secondPanel = new FilledPanel(page2Elements) { Rect = new PageRect(0, 0, 240, 150) }; bandUi.Add(new PageLayout(firstPanel)); bandUi.Add(new PageLayout(secondPanel)); return bandUi; }
That is quite a handful, right? Then for setting values to those UI element, I had this little piece of code:
private List<PageData> BuildTileData1(string timeText, string dateText, string temperature, string buttonText) { var result = new List<PageData> { new PageData(Page2Id, 1, new TextBlockData(TextTimeId, timeText)), new PageData(Page2Id, 1, new TextBlockData(TextDateId, dateText)), new PageData(Page1Id, 0, new IconData(IconId, 1)), new PageData(Page1Id, 0, new TextBlockData(TextTemperatureId, temperature)), new PageData(Page1Id, 0, new TextButtonData(ButtonToggleFanId, buttonText)) }; return result; }
And this is set to my tile using bandClient.TileManager.SetPagesAsync. Which gave me a quite puzzling result: only the last element on each page actually had a value. So that means only the datetext and the button actually showed text. As the sample in the Band SDK samples only uses one UI element, I was like, repeat adding PageData elements, right?
Wrong!
It turns out you can only add values to a PageData element once per SetPagesAsync call. So what you need to do, actually, is:
private List<PageData> BuildTileData(string timeText, string dateText, string temperature, string buttonText) { var result = new List<PageData> { new PageData(Page2Id, 1, new TextBlockData(TextTimeId, timeText), new TextBlockData(TextDateId, dateText)), new PageData(Page1Id, 0, new IconData(IconId, 1), new TextButtonData(ButtonToggleFanId, buttonText), new TextBlockData(TextTemperatureId, temperature)), }; return result; }
See the difference? Only add 2 PageData elements, one for every Page, not one for every page element data object. Maybe elementary, but I overlooked it. For quite some time. The constructors of PageData give a bit of a hint:
public PageData(Guid pageId, int pageLayoutIndex, IEnumerable<PageElementData> values); public PageData(Guid pageId, int pageLayoutIndex, params PageElementData[] values);
as the third parameter is not a page element data object but a list of it. The thing is, I created the UI on demand (when I tapped the tile) and then it worked as expected - but not the seconds time around.
It took me quite some time to figure this one out, so I thought it best to blog about it right away. Maybe I am giving help here, maybe I am just documenting my own stupidity, but nevertheless ;)
I skip the demo sample this time - if you run into this problem, you are quite far with the Band UI already, and the demo I am working on contains this code anyway and will - hopefully - arrive online soon anyway. Attentive readers will have some inkling of what that demo exactly comprises.
Happy Band coding!