Windows 10 Anniversary Update 14388, UWP, Visual Layer–Offsets on Preview SDK 14388

Just a small thing but I’m posting it here in case it helps anyone else. I spent a good few ‘minutes’ trying to figure out why this piece of XAML;

   <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        
        <Rectangle x:Name="xamlRectangle" Width="96" Height="96" Fill="Black" HorizontalAlignment="Left" VerticalAlignment="Bottom">
            
        </Rectangle>
    </Grid>

married up with this piece of code behind;

  public sealed partial class MainPage : Page
  {
    public MainPage()
    {
      this.InitializeComponent();
      this.Loaded += this.OnLoaded;
    }
    void OnLoaded(object sender, RoutedEventArgs e)
    {
      this.rectangleVisual = ElementCompositionPreview.GetElementVisual(
        this.xamlRectangle);

      this.rectangleVisual.Offset = new Vector3(100, -100, 0);
    }
    Visual rectangleVisual;
  }

Wasn’t giving me the result that I expected on Windows 10 Anniversary Update 14388 with SDK preview 14388.

What it gives me is a black rectangle which is not offset by the 100,-100 vector that I’ve specified.

1

However, if I simply retarget my project to target SDK build 10586 and run it on the same machine then I find that I get the results I expect.

2

I initially thought this was a bug but I learned that it was a change between 10586 and the builds post 14332 – the detail is here and I think I need to read it at least another 5 times before I understand it 🙂

Update

I have now read that article more than 5 times and I’m still trying to understand it although I think I have slightly more of a handle on its implications even if I don’t quite understand the mechanics.

In terms of dealing with Offset, I think I understand that if XAML thinks that it has set some value for Visual.Offset then it will override whatever value I set for Visual.Offset when it comes to do a layout pass.

For example, in the code/XAML scenario that I have further up in this post I have a Rectangle which is set to be arranged in the Bottom/Left of its parent Grid.

I also have a Loaded event handler which attempts to set the Offset property to (100,-100,0) and on SDK 14388 nothing happens whereas on 10586 the offset gets applied.

It’s worth saying that the same thing appears to happen if I try and start an animation which targets “Offset” from the Loaded handler – it doesn’t do anything on 14388.

Why? Because after my code changes the Offset value to (100,-100,0) XAML is doing a layout pass and setting it back to whatever value is necessary to position the rectangle at the bottom left of the Grid.

If I change my Loaded handler to something like this;

    async void OnLoaded(object sender, RoutedEventArgs e)
    {
      this.rectangleVisual = ElementCompositionPreview.GetElementVisual(
        this.xamlRectangle);

      await Task.Delay(5000);

      this.rectangleVisual.Offset = new Vector3(100, -100, 0);
    }

then I notice different behavior in that after 5 seconds the rectangle disappears 🙂 Why? Presumably because my asynchronously waiting for 5 seconds gives the thread time to go back and process the layout work before completing this function which then applies an Offset of (100,-100,0) from the origin of the Window which makes the rectangle (at 96 pixels high) disappear.

If I then resize the Window to force another layout pass then the Rectangle re-appears back in the bottom left hand corner of the Window.

So, the XAML layer has had to take an active hand in the positioning of this Rectangle and it attempts to reassert its authority every time it does a layout.

However, if I change my XAML such that the VerticalAlignment of the Rectangle is set to “Top” then the XAML layer doesn’t explicitly set the Visual.Offset value on any of its layout passes and so there’s no need for the artificial delay that I added into the code – the Rectangle positions itself off screen from the start and stays that way regardless of resizing the Window because the XAML pieces have never been involved in explicitly setting the Offset property in the first place.

I must admit that I find this a little tricky to reason about and I guess that it would lead me towards not letting XAML position elements that I then wanted reposition using the Visual layer although that feels a bit restrictive in terms of not being then able to use a lot of ‘goodness’ that XAML’s layout system can give me like proportional sizing and so on. I perhaps need to experiment a little more with this to figure out more around how it works and how to best code with it rather than against it 🙂

Update 2

Rob has written a post here which digs into more detail around what I was seeing in this post and I think the 2 diagrams that he’s posted help massively in explaining what happens in the Anniversary Update versus the November Update.

2 thoughts on “Windows 10 Anniversary Update 14388, UWP, Visual Layer–Offsets on Preview SDK 14388

Comments are closed.