Differences in application layouts in the Windows Store

I use Viewbox to scale a canvas of a fixed size (containing various paths that together form a meaningful picture).

<StackPanel Background="Red" Width="400" UseLayoutRounding="True"> <StackPanel.Resources> <Style TargetType="Viewbox"> <Setter Property="Height" Value="400" /> <Setter Property="Margin" Value="0,0,0,50" /> </Style> <Style TargetType="Path"> <Setter Property="Stroke" Value="Blue" /> <Setter Property="StrokeThickness" Value="2" /> </Style> </StackPanel.Resources> <Viewbox> <Canvas Width="5" Height="5"> <Path Data="M 1,1 h 3 v 3 h -3 z" /> </Canvas> </Viewbox> <Viewbox> <Canvas Width="6" Height="6"> <Path Data="M 1,1 h 4 v 4 h -4 z" /> </Canvas> </Viewbox> </StackPanel> 

This xaml appears as shown above when displayed on my PC and as shown below when displayed on the emulator. Since the emulator creates the desired result, can someone explain to me why the second way goes beyond the red panel?

rendered natively on my PCrendered on an emulator

+6
source share
2 answers

There really is no difference ... what happens because you accept what makes it very small (your path is very small):

screenshot

Look at the little boxes

... and scaling it extremely large and telling the layout to round to the nearest whole pixel via UseLayoutRounding

the reason the result is unreliable is because Path scales independently of the Canvas , since it does not actually compose its contents. Therefore, when one of your paths falls on an uneven pixel border (which can happen at some screen resolutions, and not at others), it is rounded to the nearest virtual pixel inside an unscaled canvas, and it becomes scaled from the Viewbox and then rounded to the nearest whole pixel (using the same Viewbox scale defined by Canvas scaling), exacerbating the rounding error. You can see this more easily if you turn off StackPanel.Background (transparent by default), set the Canvas.Background parameter to green and type the opacity of the stroke color:

screenshot

you can see that rounding the path is different from the canvas

Thus, you need to disable UseLayoutRounding so that decimal points are executed in the operation or simplified so that errors do not occur.

For example, if you allow the paths to scale themselves by removing the inappropriate and extra fixed-size canvas and setting Path.Stretch = Uniform , you get:

  <StackPanel Background="Red" Width="400" UseLayoutRounding="True"> <StackPanel.Resources> <Style TargetType="Viewbox"> <Setter Property="Height" Value="400" /> <Setter Property="Margin" Value="0,0,0,50" /> </Style> <Style TargetType="Path"> <Setter Property="Stroke" Value="Blue" /> <Setter Property="StrokeThickness" Value="2" /> <Setter Property="Stretch" Value="Uniform" /> </Style> </StackPanel.Resources> <Viewbox> <Path Data="M 1,1 h 3 v 3 h -3 z" /> </Viewbox> <Viewbox> <Path Data="M 1,1 h 4 v 4 h -4 z" /> </Viewbox> </StackPanel> 

, as a result: screenshot

perhaps what you really were looking for

However, if it was more simplified, and in fact you have several paths that you intended to insert into your Canvas , I suggest you use a container that actually makes its own layout, the obvious choice is Grid so you still You can scale yourself using the Grid , holding them in lock mode ( Canvas will not place your children). The code will look like this:

  <StackPanel Background="Red" Width="400" UseLayoutRounding="True"> <StackPanel.Resources> <Style TargetType="Viewbox"> <Setter Property="Height" Value="400" /> <Setter Property="Margin" Value="0,0,0,50" /> </Style> <Style TargetType="Path"> <Setter Property="Stroke" Value="Blue" /> <Setter Property="StrokeThickness" Value="2" /> <Setter Property="Stretch" Value="Uniform" /> </Style> </StackPanel.Resources> <Viewbox> <Grid Width="5" Height="5"> <Path Data="M 1,1 h 3 v 3 h -3 z" /> </Grid> </Viewbox> <Viewbox> <Grid Width="6" Height="6"> <Path Data="M 1,1 h 4 v 4 h -4 z" /> </Grid> </Viewbox> </StackPanel> 

, and the result is identical to the result without an additional container

hope this helps -ck

+5
source

I could reproduce the problem on my machine with an emulator at a 2560x1440 screen resolution with canvas, as shown below.

 <Canvas Width="4" Height="4"> <Rectangle Width="4" Height="4" Fill="Blue" ></Rectangle> </Canvas> 

For the above fragment - overflow of the canvas / goes beyond the red panel.

 <Canvas Width="6" Height="6"> <Rectangle Width="6" Height="6" Fill="Blue" ></Rectangle> </Canvas> 

For the above fragment - the canvas is omitted / does not fit the red panel and leaves some space on the right edge of the red panel.

if the canvas size is supported by a multiple of 5, it fits correctly on the red panel.

This does not seem to be a problem with Path, since it also reproduces with rect. This seems to be a problem with ViewBox scaling. I found that with UseLayoutRounding="False" on the panel stack - problems do not reproduce. I also found a related thread regarding ViewBox scaling issues. He suggests using the SnapsToDevicePixels property, but this is not available for SnapsToDevicePixels Windows storage applications.

In general, these are apparently problems with ViewBox scaling, although I'm not a professional with internal knowledge of scale scaling. A possible workaround is to set UseLayoutRounding to false if it passes the test on another machine. Plenty 5 doesn't seem like a good workaround, but you can check. In a separate note - if you are just curious to know why this happens, you get an answer and may be insufficient or overcrowded from several pixels, it may matter for your application.

+1
source

All Articles