Updated LayoutRules Code
I updated the LayoutRules sample attached to the //build/ post I made the other day. This version is much more comprehensive and easier to use. The sample usage is slightly more realistic, as well.
At its core, the sample exposes a LayoutableUserControl and a LayoutablePage that let you specify a set of layout rules that are evaluated every time the control is re-measured. Each rule implements the ILayoutRule interface that exposes a mechanism to check if the rule applies given the control's current size (ILayoutEvaluator.Evaluate) and a mechanism to invoke the functionality of the rule (ICommand.Execute).
From there some primitive layout evaluators (like WidthLayoutEvaluator - checks if the current control's width is smaller than a given width or not), some primitive commands (like GoToVisualStateCommand - goes to a named visual state), some compound evaluators / commands, and some more complex base types are defined.
The end result is a set of high-level rules that can be used for many basic operations. For example, one of the rules used in the sample is the following WidthUpdatePropertyRule:
<layout:WidthUpdatePropertyRule
DisplayName="Make buttons smaller"
Width="550"
ComparisonType="LessThan"
Name="ExplorerViewProperties"
Property="ButtonSize"
Value="50,50"
ValueIfFalse="80,80"
ValueConverter="{StaticResource SizeConverter}" />
As the DisplayName property indicates, this is used to update the ButtonSize property of the ExplorerViewProperties named resource to 50x50 if the Width of the control is less than 550px, or to 80x80 if not. Parts of the UI are data-bound to this object, and so they will update dynamically.
Another example:
<layout:HeightGoToVisualStateRule
DisplayName="Make text smaller"
Height="300"
ComparisonType="GreaterThanOrEqualTo"
VisualStateName="LargeText"
VisualStateNameIfFalse="SmallText"/>
This rule switches to the visual state LargeText if the Height is at least 300px, otherwise it switches to the SmallText visual state.
Of course, all pixel values are in effective pixels (aka view pixels). We don't care what the actual physical resolution of the display is. You can also use some of the building-blocks to make more complex rules (at the expense of more XAML).
You might ask yourself why something like this doesn't come standard as part of the platform or the SDK. When we were working on Windows Phone 8.1, we had many discussions about this very topic, but ultimately we didn't ship any layout-helper controls like those in this sample for two basic reasons:
- There is no tooling experience (Visual Studio or Blend design surface) for these layout rules; you need to reason about them without being able to see the results (or, more likely, take a starting guess and then use trial-and-error to perfect it). There is a tooling experience for Visual States, but not for automatically switching between them while designing the control
- We weren't able to settle on what the right long-term approach should be for adaptive layout. This is just one approach of many possible approaches, and whilst it is convenient for some scenarios we don't (yet) know what the best solution will look like in the future
Anyway, until such time as we solve the problem in some hypothetical future release, you can use this code (or hack it any way you see fit) in order to get your own apps up and running. If you have comments, suggestions, etc. feel free to post them below!
(P.S. I apologize for the lack of comments in the code. Hopefully when I do a full blog post for the //build talk I will have the code properly commented... and maybe even tested!)
Comments
Anonymous
April 07, 2014
blogs.msdn.com/.../trying-something-new-the-windows-phone-developer-blog.aspx links to a no-signpost blog that once was listed here http://blogs.windows.com/b/ but no longer. Has everyone left? Not much was there but if that's all there was, then there's even less now.Anonymous
April 07, 2014
Hi Jerome, thanks for posting. I tried the link in that article and it works as expected. It links to blogs.windows.com/.../wpdev which is regularly updated with new content.Anonymous
April 07, 2014
Righto the link in the article works but the link is the only way to get there. The link used to be in the http://blogs.windows.com/b/ under the Windows Phone section. It was called WP Develeoper or like that, with WM 6 Developer under that. Now not there. A very recent thing. For example, this blogs.windows.com/.../wpdev but then if you back up one directory to blogs.windows.com/.../b (weirdly, the same place as http://blogs.windows.com/b/ which only has one link to WP, and that is not dev-related) no link forward to it. Anyway, just pointing out another thing that makes following WP hard. The way I hear anything dev related about WP is at wpcentral.com, and that is not a godo thing, but I would know even less about WP if not for the occasional article there.Anonymous
April 08, 2014
Ahh, I see now. I have passed this along. Thanks for pointing it out.Anonymous
April 08, 2014
Thanks Jerome. I spoke to some folks here and the answer is that the "Phone" developer blog was merged with the "Windows" developer blog, so now there is just one: the "Building Apps for Windows" blog listed on that summary page. The old links to the Phone blog still work, but there is no link from the main page any more. I understand this is in a state of flux right now, but rest assured the content is still there and being added to on a regular basis. It's just missing the word "Phone" in the title due to the just-announced "Universal Apps" approach we're taking moving forwards.Anonymous
April 13, 2014
Hey Peter, thank you very much - great talk - it should be required viewing for all Store/Phone app developers! Is there any chance you could share your tic-tac-toe example to show more detail on how the visual states are implemented and the bits are used in a more realistic example? Thanks again, BobAnonymous
April 17, 2014
Bob, I'm working on cleaning it up and getting it posted along with an official blog sometime soon... probably means next week or two. Thanks for asking!Anonymous
April 22, 2014
Thanks Peter - another quick question for you: I want to change (hide/show) a control on a Hub page (flip from a Gridview to a Listview when width < x). I am guessing this isn't possible via the WidthGoToVisualStateRule as the target controls are inside a DataTemplate and therefore not accessible. So I decided to refactor the two controls into a user control. Unfortunately, the control width always computes as Infinity (I assume since it can scroll right and there is no width set on the HubSection). I would prefer to do this at the page level (reach into the DataTemplate) but both scenarios are probably valid. Any suggestions or hints? Thanks, BobAnonymous
April 22, 2014
Bob, it sounds like you would be better off using the WidthUpdatePropertyRule and then have your items data-bind to the value being updated. This is how the "ribbon buttons" in the sample app get larger or smaller, but you would use it for Visibility instead.Anonymous
May 04, 2014
Thanks for the 4 to 40 inches talk. It helped cement some approaches to cross platform software design and a better approach to responsive design apps. I have taken a look at your sample app and LayoutRules api, but I found it quite verbose and not easy to read the intent from the xaml code. Like many developers, I thought I would have a go myself and see if a different approach would suit my needs better. After a few iterations, I have landed with an approach I have called DynamicStyle. github.com/.../DynamicStyle nuget DynamicStyle The basic premise of the library is to set the Style of a control, depending of the shape of the screen. <TextBlock Text="Some Heading" dynamic:Dynamic.Style="Title"/> When the app is run normally, the control has a Style of "Title", but when the app is snapped or run in a portrait layout, the Style is set to "Title.Tall", and when the screen is huge, the Style is set to "Title.XWide". The different style suffices can be user defined.Anonymous
May 05, 2014
Brian, thanks for posting and for sharing your solution as well. The LayoutRules code might be overkill for some scenarios where your DynamicStyle approach will work better. (My code started out like yours, but grew in complexity as I tried to do handle more and more layout cases declaratively).