Effect on all buttons in Xamarin Forms - xaml

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)

Related

Custom control with text box and text block

I would like to build a validation text box, which would be a normal UWP TextBox wrapped within a StackPanel, which also contains a TextBlock. The intent is that a validation message can be shown beneath the text box when there is a validation error.
I know I can do this by creating a custom control, but this would require me to implement all the properties I need and create a bunch of dependency properties, etc.
I'm hoping there is an easier way, where I can just completely derive the text box, but override the display template for it and include a label beneath it.
You can get most of the way there in XAML using the built-in IDataErrorInfo-based validation machinery and defining a control template for the TextBox's Validation.ErrorTemplate. There's a pretty good article at this link:
The XAML from the article at the link above follows, also check out this discussion on WPF's built-in validation here.
<Style TargetType="{x:Type Label}">
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,2,40,2" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true">
<Border Background="OrangeRed" DockPanel.Dock="right" Margin="5,0,0,0"
Width="20" Height="20" CornerRadius="5"
ToolTip="{Binding ElementName=customAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center"
FontWeight="Bold" Foreground="white" />
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Xamarin.Forms setting specific style for platform

I'm trying to style my UWP application with some specific styles, while on other platforms it should remain default.
This is my project layout:
I tried the following things:
In Clients.Shared creating a style as following:
<Style x:Key="SomeStyle" TargetType="Button" />
And adding the same Style key in the Clients.Themes.UWP so it could hopefully override it, but no luck.
Then I tried Having a Dummy Style and using the onPlatform but that didn't work either, but I still think this is the way to go. I had the following code:
<Style x:Key="DummyStyle" TargetType="Button">
<Setter Property="Style">
<Setter.Value>
<OnPlatform x:Key="ButtonStyle" x:TypeArguments="Style">
<On Platform="UWP" Value="{StaticResource SomeStyle}"></On>
</OnPlatform>
</Setter.Value>
</Setter>
</Style>
I tried messing around with merged ResourceDictionary.MergedDictionaries but there I couldn't include the xaml
Anybody have any clue?
Try this:
<OnPlatform x:TypeArguments="Color" Android="Green" iOS="White" WinPhone="White"
x:Key="PrimaryColor" />
<Style x:Key="ButtonColor" TargetType="Button">
<Setter Property="BackgroundColor" Value="{StaticResource PrimaryColor}" />
</Style>
<Button Text="Hello" HorizontalOptions="StartAndExpand"
Grid.Row="2" Grid.ColumnSpan="2" Style="{StaticResource ButtonColor}" />
In this example, I am defining a style for a Button called ButtonColor. This Button will use a BackgroundColor of white for all platforms except Android where it will be Green.
I find this is the most common use for this tag with regard to styling; if you are working with fonts, be sure to run on simulator and actual devices to get the font that you want.
This syntax works for me:
<Style x:Key="zoneLabelStyle" TargetType="Label">
<Setter Property="HeightRequest" Value="18" />
<Setter Property="Margin">
<OnPlatform x:TypeArguments="Thickness">
<On Platform="Android" Value="0, -3, 0, 0" />
</OnPlatform>
</Setter>
</Style>
Why do not use
<Button.Style>
<OnPlatform x:TypeArguments="x:Style">
<OnPlatform.iOS>...</OnPlatform.iOS>
<OnPlatform.Android>...</OnPlatform.Android>
<OnPlatform.WinPhone>...</OnPlatform.WinPhone>
</OnPlatform>
</Button.Style>
Hope it will help.

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.

Setting imagesource of image inside controltemplate for different controls in xaml

I have created a Style for circular button in windows application. I am using this style to make the buttons appear circular. Code for the Style is below:
<Style x:Key="CircularButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Stroke="#FFF8F1F1" />
<Image Width="50" Height="50" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am using like below :
<Button x:Name="btnFacebook" Style="{StaticResource CircularButton}" Click="btnFacebook_Click" Visibility="Visible" Margin="10,0" />
Now I have many buttons on the page that need to be circular,but need to have different background images.Is there any way to set the image source of this style for different buttons.I have tried code like below:
<Button x:Name="btnTwitter" Style="{StaticResource CircularButton}" Click="btnTwitter_Click" HorizontalAlignment="Stretch" Margin="10,0">
<ControlTemplate>
<Image Source="Images/appbar.social.twitter.png"/>
</ControlTemplate>
</Button>
Also I have tried placing the image directly inside the button content , or using the template binding for showing the image inside the button.Is there any way of doing this without creating different styles for different buttons.
something like this:
<Style x:Key="CircularButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Stroke="#FFF8F1F1" />
<Image Width="50" Height="50" Source="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button x:Name="btnTwitter" Style="{StaticResource CircularButton}" Click="btnTwitter_Click" HorizontalAlignment="Stretch" Margin="10,0">
<BitmapImage UriSource="Images/appbar.social.twitter.png"/>
</Button>

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!