Reputation: 1674
I'm building a Universal App based off work I've done on a Windows 8.1 app. In that app, I make use of Paths in order to display various icons in the highest quality possible.
I do this with a style:
<Style x:Key="UnstyledGraphicsButtonStyle" TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Path Width="{Binding Width, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding Width, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Stretch="Uniform"
Fill="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Data="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="0">
<ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalAlignment="Left" Margin="6,4" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" FontFamily="Global User Interface"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This then gets used in an item template but, for the purposes of testing, here is some example XAML that is representative of the item template:
<Grid Margin="6" HorizontalAlignment="Left">
<Border Background="#FF4068B2" Width="60" Height="60">
<Button Content="M28.770002,34.487999 L52.512001,34.487999 C57.570004,34.487999 61.676003,38.592999 61.676003,43.655998 L61.676003,66.703003 L19.609001,66.703003 L19.609001,43.655998 C19.609001,38.592999 23.711002,34.487999 28.770002,34.487999 z M55.210999,20.660004 L71.980995,20.660004 C76.409996,20.660004 80,24.250004 80,28.679003 L80,48.601002 L63.987999,48.601002 L63.987999,41.539001 C63.987999,36.476002 59.394997,32.375 53.723,32.375 L49.343998,32.375 C52.898998,29.796003 55.223,25.617002 55.223,20.890003 C55.223,20.812002 55.210999,20.738003 55.210999,20.660004 z M8.0200005,20.660004 L26.851999,20.660004 C26.851999,20.734003 26.84,20.808002 26.84,20.882004 C26.84,25.597004 29.149,29.765001 32.687996,32.343006 L27.125,32.343006 C21.452999,32.343006 16.859001,36.449005 16.859001,41.507004 L16.859001,48.597004 L0,48.597004 L0,28.679003 C0,24.250004 3.5940018,20.660004 8.0200005,20.660004 z M41.031006,9.156002 C47.512005,9.156002 52.762005,14.406003 52.762005,20.882004 C52.762005,27.363005 47.512005,32.613003 41.031006,32.613003 C34.555,32.613003 29.305004,27.363005 29.305004,20.882004 C29.305004,14.406003 34.555,9.156002 41.031006,9.156002 z M61.922005,0 C66.781006,-1.6088339E-07 70.719002,3.9409997 70.719002,8.8000002 C70.719002,13.656001 66.781006,17.597 61.922005,17.597 C57.063004,17.597 53.125004,13.660001 53.125004,8.8000002 C53.125004,3.9409997 57.063004,-1.6088339E-07 61.922005,0 z M17.355999,0 C22.215002,-1.6088339E-07 26.156002,3.9409997 26.156002,8.8000002 C26.156002,13.656001 22.215002,17.597 17.355999,17.597 C12.496002,17.597 8.5590019,13.660001 8.5590019,8.8000002 C8.5590019,3.9409997 12.496002,-1.6088339E-07 17.355999,0 z" Style="{StaticResource UnstyledGraphicsButtonStyle}" Width="50" Height="41.689375" Foreground="white" Padding="0" Background="transparent" BorderBrush="{x:Null}" IsEnabled="False" />
</Border>
</Grid>
In Windows 8.1, this renders perfectly with the Path centered in the button:
However, on Windows Phone 8.1, it renders like this:
It should be noted that the hard-coded width and height values in the example are not normally hard-coded. They are set through the template. The above is just an example to show how the rendering differs between the two platforms. An example of how it get used is:
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60" Visibility="{Binding ImageIsAvailable, Converter={StaticResource HideIfTrue}}">
<Button Content="{Binding ImageContent}" Style="{StaticResource UnstyledGraphicsButtonStyle}" Width="{Binding ImageWidth50}" Height="{Binding ImageHeight50}" Foreground="white" Padding="0" Background="Transparent" BorderBrush="{x:Null}" IsEnabled="False" />
</Border>
In other words, I set the border to be a certain square width and height, and then I specify how wide I want the button to be, namely 10 pixels less. The binding is done because the various paths have different actual widths and heights, so the code adjusts them to get them to look good in a 50x50 square.
The only solution I've found is to add the following to the end of the Border statement in the template:
Width="60" Height="60" HorizontalAlignment="Left"
so that it reads
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="0" Width="60" Height="60" HorizontalAlignment="Left">
Now, the problem with that is that the width and height are then hard-coded rather than being set by the parent object(s). Although the example above uses a 60px boarder and a 50px button, I have places in my app where different sizes are used, hence the desire to avoid hard-coding dimensions in the template.
Have I done something wrong in my XAML to explain why Windows Phone XAML behaves this way?
What is the cleanest/best way to fix it?
Thanks.
Philip
Upvotes: 1
Views: 708
Reputation: 36
Try putting the path data into a path nested in a Viewbox like the below?
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}"
Width="60"
Height="60"
Visibility="{Binding ImageIsAvailable, Converter={StaticResource HideIfTrue}}">
<Button Style="{StaticResource UnstyledGraphicsButtonStyle}"
Width="{Binding ImageWidth50}"
Height="{Binding ImageHeight50}"
Foreground="white"
Padding="0"
Background="Transparent"
BorderBrush="{x:Null}"
IsEnabled="False" >
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<Path Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Width="{Binding ImageWidth50}"
Height="{Binding ImageHeight50}"
StrokeThickness="2"
Stretch="Uniform"
Data="Path Data Here" />
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</Border>
Upvotes: 2