Xamarin UWP custom CommandBar - xaml

I'd like to create a custom CommandBar for the UWP part of my Xamarin project.
I want to make a logo on a background color. The only way to get this, is making a visualbrush or grid, to contain both the background color and the picture.
I've read it can be done like so;
<Window.Resources>
<VisualBrush x:Key="myBrush">
<VisualBrush.Visual>
<Grid>
<Rectangle Fill="Red" />
<Image Source="troll.png" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Window.Resources>
I need to add this commandbar during runtime like so:
var _globalAppBar = new CommandBar();
_globalAppBar.Background = [Link to above layout]
Questions:
How or where can I add this in my Xamarin UWP project? Add a XAML file?
How can I link during run time to the layout? Or is there a better way to do this?

Ideally, you would create a new style for the CommandBar and add it to the App.xaml resource dictionary
<Application.Resources>
<Style TargetType="CommandBar">
<Setter Property="Background">
<Setter.Value>
<VisualBrush>
<VisualBrush.Visual>
<Grid>
<Rectangle Fill="Red" />
<Image Source="troll.png" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
because the style has no key, it will become the implicit style for CommandBar and therefore be applied to all CommandBar instances

Related

Effect on all buttons in Xamarin Forms

I'm trying to have a effect on all my buttons, but I can't seem to get the configuration right.
this is what I have now:
<ResourceDictionary>
<ControlTemplate x:Key="ButtonTemplate" >
<Grid RowSpacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<ContentPresenter Grid.Row="0" Grid.Column="0" >
<ContentPresenter.Effects>
<effects:ShadowEffect Radius="5" DistanceX="5" DistanceY="5">
<effects:ShadowEffect.Color>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="Black" />
<On Platform="Android" Value="White" />
<On Platform="UWP" Value="Red" />
</OnPlatform>
</effects:ShadowEffect.Color>
</effects:ShadowEffect>
</ContentPresenter.Effects>
</ContentPresenter>
</Grid>
</ControlTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="ControlTemplate" Value="{StaticResource ButtonTemplate}"></Setter>
</Style>
</ResourceDictionary>
But this throws a Can't resolve ControlTemplateProperty on Button.
Anybody has any idea on how to do this?
As you can see at Xamarin.Forms Guides the Control Templates isn't applicable to Button.
A ControlTemplate can be applied to the following types by setting
their ControlTemplate properties:
ContentPage
ContentView
TemplatedPage
TemplatedView
The error Can't resolve ControlTemplateProperty on Button make sense. Button inherites from View, not TemplatedView as would be needed.
So about your main point, effects cann't consumed directly by style, but you can achieve this thru attached properties. Here is some good references to you:
How to create an effect
How to consume it with styles
A good example
I hope it help you (and sorry for my bad english)

UserControl style only visible in designer

I'd like to have page headers in my app with either an icon or text centered in a 50px high bar at the top of the page. Optionally with a back-button.
For this reason I use a UserControl on each page which gets either one of those styles applied: PageHeaderStyle or PageHeaderBackStyle.
My implementation of one of those is the following (style definition in my App.xaml):
<Style x:Key="PageHeaderBaseStyle" TargetType="UserControl">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Height" Value="50" />
<Setter Property="Width" Value="NaN" />
<Setter Property="Background" Value="{StaticResource CDColor}" />
</Style>
<Style x:Key="PageHeaderStyle" TargetType="UserControl" BasedOn="{StaticResource PageHeaderBaseStyle}">
<Setter Property="Content">
<Setter.Value>
<Grid Background="{StaticResource CDColor}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DataContext="{StaticResource MainPageModel}">
<TextBlock Style="{StaticResource PageHeaderTextBlockStyle}" Text="{Binding Title}" Visibility="{Binding TitleVisibility}" />
<Image Style="{StaticResource PageHeaderIconStyle}" Source="{Binding Icon}" Visibility="{Binding IconVisibility}" />
</Grid>
</Setter.Value>
</Setter>
</Style>
Applied like it should be:
<UserControl Style="{StaticResource PageHeaderStyle}" />
Now first I had used "Template" and applied a DataTemplate with the grid component. But this didn't work. Then I changed it to directly set the Content of the UserControl. This does work: After building the designer shows the page header (before it showed only the blue selection border, but no content - it was transparent).
But as soon as I start debugging the app on the emulator it disappears and the running app only shows a blank spot where it should be.
Why is this so? I mean after all the designer already shows it, why does it disappear then, though?
FYI: I do not get any binding exceptions nor any other. It just doesn't show up.
PS: I tried setting the Background in the base style while setting the grid's background to transparent. This didn't work either - only a blank spot.
Solved the problem: Best approach is probably to use a ContentControl. Using the Content property did not work, though. You have to use the ContentTemplate property. Using that one does work just fine.

Windows Store app's overriden resource value ignored in template

I'm creating a Windows Store app where each page has a dominant color used for titles, buttons and such.
In App.xaml I've created a default Brush that's overriden in each Page's xaml file, and a style template for Buttons which I reuse in every page. The templates are supposed to use the page's color but for some reason they stick with the default value.
Here are my xaml files.
App.xaml
<Application
x:Class="Foo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Foo"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<SolidColorBrush x:Name="SectionDefaultBrush" Color="Red" />
<Style TargetType="Button" x:Name="NavigationButtonStyle">
<Setter Property="FontFamily" Value="Myriad Pro" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle x:Name="Border" Fill="#f4f4f4" Margin="0" />
<TextBlock Foreground="{ ThemeResource SectionDefaultBrush }" Text=">" FontSize="31" />
<ContentPresenter x:Name="Content" VerticalAlignment="Center" Foreground="#5A5A5A" HorizontalAlignment="Left" FontSize="31"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
SomePage.xaml
<Page
x:Class="Foo.Pages.SomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<SolidColorBrush x:Key="SectionDefaultBrush" Color="Green" />
</Page.Resources>
<ViewBox>
<Canvas>
<TextBlock Text="Some text" Foreground="{ ThemeResource SectionDefaultBrush }" Canvas.Left="130" TextWrapping="Wrap" Canvas.Top="252" Height="177" Width="507" FontFamily="Myriad Pro" FontSize="54" />
<Button Content="Click me" Style="{ ThemeResource NavigationButtonStyle }" Canvas.Left="130" Canvas.Top="900" Width="507" Height="48" />
</Canvas>
<ViewBox>
In this example, the TextBlock's text color is green as expected (and red if I remove the Brush from Page.Resources), but the Button's content remains red. Is there a way to tell the template to use the final color ?
The app's resource dictionary doesn't know about other dictionaries and unlike with WPF's DynamicResources - StaticResource isn't reevaluated and ThemeResource is, but I think only when the actual theme changes. The way you can customize the color of that button is to use TemplateBinding in the template and bind to say the Foreground property of the button and also set that in the Foreground Setter of your button style to {StaticResource SectionDefaultBrush}. Then in your page you can override that by setting the Foreground of the button to a different value or using a derived button style that changes the Foreground value.
Ideally too - you should define theme resources in your dictionary so the brushes change depending on OS theme (especially high contrast). You might want to name your brush then as "SectionDefaultThemeBrush" instead of just "SectionDefaultBrush".

XAML style is applied to only the first rectangle. How to make it apply to all?

In a Windows 8 (WinRT) app, I am creating my own XAML style to get a dotted rectangle. In the setter for the style, I use Property="StrokeDashArray" Value="1,4". I then create a bunch of rectangles, and then explicitly set the style of those rectangles to this style I created. The first rectangle shows up with a dotted border - but the other two don't. However, if in addition to the Style={StaticResource myDottedStyle} I also specify the StrokeDashArray with each rectangle, then all them correctly show up with dotted borders.
Why is the dotted border only showing up for the first rectangle? How can I create a Style that is applied to all the rectangles without specifying the StrokeDashArray for each of them?
Here is a full code sample. In Windows 8 RTM, create a Blank XAML app project, and replace the Grid in the MainPage.xaml with the following:
<Page.Resources>
<Style x:Key="myDottedStyle" TargetType="Rectangle">
<Setter Property="Stroke"
Value="{StaticResource ApplicationForegroundThemeBrush}"/>
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="StrokeDashArray" Value="1,4"/>
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Rectangle Style="{StaticResource myDottedStyle}" Width="40"
HorizontalAlignment="Left"/>
<Rectangle Style="{StaticResource myDottedStyle}" Width="40"
HorizontalAlignment="Center"/>
<Rectangle Style="{StaticResource myDottedStyle}" Width="40"
HorizontalAlignment="Right"/>
</Grid>
Here is a screenshot of the output of this
I found a related question that talks about DataTemplates here but I can't figure out how to translate that into my problem.
You could optimize things a bit by not requiring it to re-draw the rectangle per each instance and substitute for a ContentControl instead since they appear the same but with minor differences. So something for example like;
<Style x:Key="MyDottedStyle" TargetType="ContentControl">
<!-- Add additional Setters Here -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Rectangle Stroke="{StaticResource ApplicationForegroundThemeBrush}"
StrokeThickness="2"
StrokeDashArray="1,4"
Width="40" Height="40"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
Margin="{TemplateBinding Margin}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- And now actually place it on your view -->
<ContentControl Style="{StaticResource MyDottedStyle}" HorizontalAlignment="Center"/>
This will allow you to not only clean things up because you can take your Style template and slap it over into say a Resource Dictionary to reduce clutter, but also makes it a little more efficient since you're not re-drawing your shape every time it's required. Hope this helps! Cheers!

How to set page background in metro application

I have strange problem. I can't set background for my page in metro app.
Below is a simple view of my xaml structure
<Page Background="White">
<ListView Background="Red">
</ListView>
</Page>
The problem is that the background of the page is black. So I have red rectangle (ListView area) set on black background. I want my page to be white. I saw few examples and it seems that I did good. I've also tried with brushes but same result.
If you want your app to have a white background on all pages, then the easiest way to achieve this is to set the RequestedTheme on Light in the App.xaml file. This will not only give you a white background, but it will automatically change all other colors too, like the foreground color (for text etc.) will be black by default.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
RequestedTheme="Light">
For a single page I've always used a grid as rootcontainer in a page and that worked fine:
<common:LayoutAwarePage
x:Name="pageRoot"
...
>
<Grid Background="White">
Note that if you want to use an image as background instead of a color, you'll have to work with attached properties:
<Grid>
<Grid.Background>
<ImageBrush x:Name="backgroundGrid" ImageSource="/Assets/Paper.jpg" />
</Grid.Background>
I think the issue you're running into is that the default style for the page is overriding your attempt to set the background color.
If you look at the file StandardStyles.xaml, it includes a LayoutRootStyle (at the very end of the file). If you change the Value from the default to a hex color value (for example, #FFFF0000 would give you red), the background of the app will be changed correspondingly. This is a simple way to do what you want, but may not be a best practice.
<Style x:Key="LayoutRootStyle" TargetType="Panel">
<Setter Property="Background" Value="{StaticResource ApplicationPageBackgroundThemeBrush}"/>
<Setter Property="ChildrenTransitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
Alternatively, you could set the background for the root Grid element, which would give you more granular control. Or you could create a custom style that overrides LayoutRootStyle in your page's Page.Resources section, by copying the rule into that section, and then modifying the Value of the Background setter.
Here's what it should look like:
<Page.Resources>
<Style x:Key="LayoutRootStyle" TargetType="Panel">
<Setter Property="Background" Value="#FFFF0000"/>
<Setter Property="ChildrenTransitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
Hope that helps.