I have resources defined in the app.xaml as below
<ResourceDictionary x:Name="myResDic" >
<!-- Styles -->
<Color x:Key="grayDark">#959595</Color>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="TextColor" Value="#4fddb7" />
<Setter Property="BorderRadius" Value="4" />
<Setter Property="FontSize" Value="Small" />
<Setter Property="BackgroundColor" Value="{StaticResource grayDark}" />
<Setter Property="HeightRequest">
<Setter.Value>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="50" />
</Setter.Value>
</Setter>
</Style>
<Style x:Key="wizardButton" TargetType="Button" BasedOn="{StaticResource buttonStyle}">
<Setter Property="BackgroundColor" Value="#3FFF" />
<Setter Property="BorderColor" Value="#AFFF" />
<Setter Property="TextColor" Value="#4fddb7" />
<Setter Property="BorderWidth" Value=".5" />
</Style>
if I bind it to a button like that in xamarin forms contentpage, it works fine
<Button Text="Login with Facebook" Image="facebook.png"
VerticalOptions="EndAndExpand" Style="{StaticResource wizardButton}"/>
But I create a custom button using ButtonRenderers in Android with the code below. But using like that style is not working correctly. Borders are not appearing. See the screenshot below. It is inheriting Button, why doesnt it work?
<controls:FacebookLoginButton Text="Login with Facebook" Image="facebook.png" VerticalOptions="EndAndExpand" Style="{StaticResource wizardButton}"/>
<Button Text="Skip" Style="{StaticResource wizardButton}"/>
public class FacebookLoginButton : Button
{
public FacebookLoginButton()
{
}
}
Obviously buttonrenderer is causing this problem. when I exclude it, it works fine. here is how my android buttonrenderer class looks like
using System;
using Android.App;
using Android.Content;
using Xamarin.Forms.Platform.Android;
using Object = Java.Lang.Object;
using View = Android.Views.View;
using Xamarin.Facebook;
using myApp.Helpers.Controls;
using myApp.Droid;
using Android.Widget;
[assembly: Xamarin.Forms.ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRendererAndroid))]
namespace myApp.Droid
{
public class FacebookLoginButtonRendererAndroid : ButtonRenderer
{
private static Activity _activity;
public FacebookLoginButtonRendererAndroid(Context context)
: base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
_activity = this.Context as Activity;
//DEBUG
//Xamarin.Facebook.Login.LoginManager.Instance.LogOut();
if (this.Control != null)
{
Button button = this.Control;
button.SetOnClickListener(ButtonClickListener.Instance.Value);
}
if (AccessToken.CurrentAccessToken != null)
{
App.PostSuccessFacebookAction(AccessToken.CurrentAccessToken.Token);
}
}
private class ButtonClickListener : Object, IOnClickListener
{
public static readonly Lazy<ButtonClickListener> Instance = new Lazy<ButtonClickListener>(() => new ButtonClickListener());
public void OnClick(View v)
{
var myIntent = new Intent(_activity, typeof(FacebookActivity));
_activity.StartActivityForResult(myIntent, 0);
}
}
}
}
There are two ways to do this.
The first is to remove the key from the style so it applies to all buttons of type FacebookLoginButton.
This is an implicit style and details can be found here
<Style TargetType="FacebookLoginButton" BasedOn="{StaticResource buttonStyle}">
<Setter Property="BackgroundColor" Value="#3FFF" />
<Setter Property="BorderColor" Value="#AFFF" />
<Setter Property="TextColor" Value="#4fddb7" />
<Setter Property="BorderWidth" Value=".5" />
</Style>
The second way is to add a bindable style property to the facebook button user control, bind it to a style in XAML and implement it in the custom renderer.
Related
In UWP, if I want to specify a default style for a custom control, I'd code it up like this:
public PriceControl()
{
// This allows the control to pick up a template.
this.DefaultStyleKey = typeof(PriceControl);
}
I can't find the equivalent in Xamarin.Forms. How do you tell a custom control that it should use a style by default?
Just define a style in App.Xaml of the typeof your control and don't give it a key just a target type and that should do the trick:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="Button">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderColor" Value="Lime" />
<Setter Property="BorderRadius" Value="5" />
<Setter Property="BorderWidth" Value="5" />
<Setter Property="WidthRequest" Value="200" />
<Setter Property="TextColor" Value="Teal" />
</Style>
</ResourceDictionary>
</Application.Resources>
Just replace button with your control and it's properties Into the setter's and this will be your global default style for this control!
i have this view
<Entry Placeholder="Name" WidthRequest="200" Text="">
<Entry.Triggers>
<EventTrigger Event="Focused">
<local:SizeText />
</EventTrigger>
</Entry.Triggers>
</Entry>
i want that when the Entry have one or more characters it be paint with other color and have the focus but when have not the focus it be paint with other color
protected override void Invoke(Entry entry)
{
if (entry.IsFocused) {
if (entry.Text.Length == 0)
{
entry.BackgroundColor = Color.Yellow;
}
}
else{
Console.WriteLine("CCCHCH");
entry.BackgroundColor = Color.White;
}
}
my don't work for me, how i can enhacement?
Try this one:
<Entry Placeholder="enter name">
<Entry.Triggers>
<Trigger TargetType="Entry" Property="IsFocused" Value="True">
<Setter Property="BackgroundColor" Value="Yellow" />
</Trigger>
<Trigger TargetType="Entry" Property="IsFocused" Value="False">
<Setter Property="BackgroundColor" Value="Red" />
</Trigger>
</Entry.Triggers>
</Entry>
I'm not sure which solution you want ,there are two ways to Change BackgroundColor of Entry .
One is Designed method ,using Triggers can easy to do that , have a look at this official document .
A simple trigger can be expressed purely in XAML, adding a Trigger element to a control's triggers collection. This example shows a trigger that changes an Entry background color when it receives focus and unfocus:
<Entry Placeholder="Trigger effect">
<Entry.Triggers>
<Trigger TargetType="Entry"
Property="IsFocused"
Value="True">
<Setter Property="BackgroundColor"
Value="Yellow" />
<!-- multiple Setters elements are allowed -->
</Trigger>
<Trigger TargetType="Entry"
Property="IsFocused"
Value="False">
<Setter Property="BackgroundColor"
Value="Gray" />
</Trigger>
</Entry.Triggers>
</Entry>
Another one is Runtime method , using Focused and Unfocused to implement it .
The VisualElement class, from which Entry inherits, also has Focused and Unfocused events.
<Entry Placeholder="Focused / Unfocused method" Focused="Entry_Focused" Unfocused="myentry_Unfocused"/>
Need dealing with events in ContentPage :
private void Entry_Focused(object sender, FocusEventArgs e)
{
var entry = sender as Xamarin.Forms.Entry;
entry.BackgroundColor = Color.Red;
}
private void myentry_Unfocused(object sender, FocusEventArgs e)
{
var entry = sender as Xamarin.Forms.Entry;
entry.BackgroundColor = Color.Gray;
}
I will show their effects , there will be some differents between them before first tapping them. As follow :
Note : It depends on your scene to choose which one .
I have a Xamarin Forms application, and the only plaftorm it supports is UWP. I use Master-Detail architecture. I understand how I can change the Title text of the Detail page, but I need to change e.g. height of the Title pane and its background color. I guess it should be done on the MySolution.UWP project, but don't know how to approach this. I don't even know what I should change, TopCommandBarArea, or CommandBar, or LayoutRoot etc.
Here is some of my code from the shared project:
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MainMDPageMenuItem;
if (item == null)
return;
item.ItemBackgroundColor = Color.FromHex("#006c89");
if (PreviouslySelectedItem != null)
{
PreviouslySelectedItem.ItemBackgroundColor = Color.FromHex("#00a8d5");
}
var page = (Page)Activator.CreateInstance(item.TargetType);
page.Title = item.Title;
Detail = new NavigationPage(page);
IsPresented = false;
MasterPage.ListView.SelectedItem = null;
PreviouslySelectedItem = item;
}
To change the Title bar background color, add below snippet in your App.Xaml which is in Xamarin Forms Project:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor"
Value="Maroon"></Setter>
<Setter Property="BarTextColor"
Value="Violet"></Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
And to change the Font Attributes, add below code snippet in your UWP project App.Xaml
<Application.Resources>
<ResourceDictionary>
<Style x:Key="TitleTextBlockStyle"
BasedOn="{StaticResource BaseTextBlockStyle}"
TargetType="TextBlock">
<Setter Property="FontWeight"
Value="SemiLight" />
<Setter Property="FontSize"
Value="36" />
<Setter Property="OpticalMarginAlignment"
Value="TrimSideBearings" />
</Style>
</ResourceDictionary>
</Application.Resources>
I have created a Xamarin.Forms application and it has quite a long name.
When I start it on my 4.5" Windows 10 phone, it looks very strange.
The main page consists of a TabbedPage and it has the Title property, however it has no FontSizeproperty.
I use the following Style in my PCL project:
<Style TargetType="Label">
<Setter Property="TextColor" Value="{StaticResource BaseColor}" />
<Setter Property="FontSize">
<Setter.Value>
<OnIdiom x:TypeArguments="x:Double"
Phone="18"
Tablet="28" />
</Setter.Value>
</Setter>
</Style>
However, if I remove it, the title is still very large.
Where can I modify the title font size to make the title smaller?
UPDATE:
I checked with the Live Property Editor, and it shows that the Title is inside the CommandBar and the FontSize is set to 24.
I tried to override its style (both in XAML and in code), but it doesn't work:
<forms:WindowsPage.BottomAppBar>
<CommandBar>
<CommandBar.Style>
<Style TargetType="CommandBar">
<Setter Property="FontSize" Value="4" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="Whatever" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</CommandBar.Style>
<CommandBar.Content>
<TextBlock Text="Whatever" />
</CommandBar.Content>
</CommandBar>
</forms:WindowsPage.BottomAppBar>
public MainPage()
{
this.InitializeComponent();
var bapp = BottomAppBar;
LoadApplication(new MyXamarinApp.App(IoC.Get<SimpleContainer>()));
BottomAppBar = bapp;
BottomAppBar.FontSize = 4;
}
Any idea?
UPDATE 2:
You can download a sample project from here.
You have to override one of the built-in styles:
<!-- Tab title -->
<Style x:Key="TitleTextBlockStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="18" />
<Setter Property="TextWrapping" Value="NoWrap" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
</Style>
I'm creating some styles for a basic property grid. The XAML for an example would be
<StackPanel Style="{StaticResource propertyGrid}" Orientation="Vertical" >
<ItemsControl Tag="property">
<Label>Nodes</Label>
<TextBox Text="{Binding Nodes}"/>
</ItemsControl>
<ItemsControl Tag="property">
<Label >Major Diameter</Label>
<TextBox Text="{Binding MajorDiameter}"/>
</ItemsControl>
<ItemsControl Tag="property">
<Label>Minor Diameter</Label>
<TextBox Text="{Binding MinorDiameter}"/>
</ItemsControl>
<ItemsControl Tag="property">
<Label>Excenter</Label>
<TextBox Text="{Binding Excenter}"> </TextBox>
</ItemsControl>
</StackPanel>
and my styling follows this logic. Labels or TextBoxes within
an ItemsControl with Tag property get special styling. If I
was doing this as psuedo CSS I'd write
ItemsControl.property Label {
Grid.Row: 0;
FontWeight: bold;
Padding:0,4,0,0;
}
ItemsControl.property TextBox {
Grid.Row: 1;
FontWeight: bold;
}
after much teeth gnashing I figured out one way to do this and this
was to use DataTriggers to look back up the tree rather than the
CSS mentality to look down the tree. However I'm rather horrified
by the verbosity of it. See below.
<Style TargetType="StackPanel" x:Key="propertyGrid">
<Style.Resources>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=Tag}" Value="property">
<Setter Property="Grid.Row" Value="0"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Padding" Value="0,4,0,0"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=Tag}" Value="property">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Grid.Row" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ItemsControl" x:Key="property">
<Style.Triggers>
<Trigger Property="Tag" Value="property">
<Setter Property="Focusable" Value="False"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
My question is. Is there a shortcut or better notation for doing this? I'm very
tempted to write a WPFCSS compiler to deal with this ;) Could I
write a MarkupExtension to clean it up. I would prefer any solutions to work
at design time as well if possible.
For example would it be possible to write an extension such as
<AncestorTrigger TargetType="ItemsControl" Path="Tag" Value="property">
<Setter Property="Grid.Row" Value="0"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Padding" Value="0,4,0,0"/>
</AncestorTrigger>
? This would be much easier than remembering how to write
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=Tag}" Value="property">
I wrote a custom behavior to solve this that also works at design time. The markup will
<DataTrigger
WPF:WhenParentTag.TargetType="{x:Type ItemsControl}" Value="property">
<Setter Property="Grid.Row" Value="0"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Padding" Value="0,4,0,0"/>
</DataTrigger>
which is a bit more sane. The code for the extension is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
namespace My.WPF
{
public static class WhenParentTag
{
static WhenParentTag()
{}
public static readonly DependencyProperty
TargetTypeProperty =
DependencyProperty.RegisterAttached
( "TargetType"
, typeof(Type)
, typeof(WhenParentTag)
, new PropertyMetadata(null, TargetTypeChanged));
public static void
TargetTypeChanged
( DependencyObject dob
, DependencyPropertyChangedEventArgs e)
{
var trigger = dob as DataTrigger;
if(trigger==null){
return;
}
var type = e.NewValue as Type;
if (type == null)
return;
var binding = new Binding();
var rel = new RelativeSource(RelativeSourceMode.FindAncestor) { AncestorType = type };
binding.RelativeSource = rel;
binding.Path = new PropertyPath("Tag");
trigger.Binding = binding;
}
public static Type
GetTargetType
( DataTrigger dp)
{
return (Type)dp.GetValue(TargetTypeProperty);
}
public static void
SetTargetType
( DataTrigger dp,
Type value)
{
dp.SetValue(TargetTypeProperty, value);
}
}
}
Improvement suggestions are welcome.