How do focus and unFocus in many entries - xamarin.forms

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 .

Related

How do I trigger a Maui DataTrigger on load

I have a DataTrigger to set some styling based on the result of a validation (it is linked to a TextValidationBehaviour). It works fine, except I want it to trigger when the page loads so the user can see what they need to fill in (i.e. Entry is red until the user types something into it).
So is there any way to trigger the validation on page load?
Here is my code, but open to suggestions:
<Frame WidthRequest="350">
<StackLayout Orientation="Horizontal">
<Entry Style="{StaticResource Key=EntryInverted}" Placeholder="Last Name" Text="{Binding LastName}">
<Entry.Behaviors>
<toolkit:TextValidationBehavior x:Name="LastNameVal"
InvalidStyle="{StaticResource InvalidEntryStyle}"
Flags="ValidateOnValueChanged"
MinimumLength="2"
MaximumLength="99" />
</Entry.Behaviors>
</Entry>
</StackLayout>
<Frame.Style>
<Style TargetType="Frame" BasedOn="{StaticResource Key=EntryFrame}">
<Setter Property="BorderColor" Value="White"/>
<Style.Triggers>
<DataTrigger TargetType="Frame" Binding="{Binding Source={x:Reference LastNameVal}, Path=IsNotValid}" Value="True">
<Setter Property="BorderColor" Value="{StaticResource FrameErrorBorder}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Frame.Style>
</Frame>
You can add a trigger to the entry, such as:
<Entry >
<Entry.Triggers>
<MultiTrigger TargetType="Entry">
<MultiTrigger.Conditions>
<PropertyCondition Property="IsFocused" Value="false"/>
<PropertyCondition Property="Text" Value="{x:Null}"/>
</MultiTrigger.Conditions>
<Setter Property="BackgroundColor" Value="Red"/>
</MultiTrigger>
</Entry.Triggers>
</Entry>
The codes above will make the entry's background color show as red. And it will show the default background color when user taps the entry.
Or you want to the entry is red if the entry has no text in it. You can try the following code:
<Entry >
<Entry.Triggers>
<MultiTrigger TargetType="Entry">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={RelativeSource Self}, Path= Text.Length}" Value="0"/>
</MultiTrigger.Conditions>
<Setter Property="BackgroundColor" Value="Red"/>
</MultiTrigger>
<Trigger TargetType="Entry" Property="Text" Value="{x:Null}">
<Setter Property="BackgroundColor" Value="Red"/>
</Trigger>
</Entry.Triggers>
</Entry>
When you use the trigger above, the entry will be red until it has been typed something.

IsSelectionActive cleared when RowDetailsTemplate clicked

I have a datagrid with row details. When I click in the row details the IsSelectionActive on the datagrid is cleared. Now this only happens on some of my datagrids while others using the exact same styles and templates exabit the correct behavior. Here is my xaml for the DataGridRow. when I click on the details view with the error the background of the detail changes to yellow. Also my IsSelected color is cleared however the IsSelected property is always set.
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=IsSelectionActive }" Value="False"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=IsSelectionActive }" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="{DynamicResource PrimaryColor}"/>
<Setter Property="Foreground" Value="White"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
Upon further research I have determined this bug occurs when the datagrid is wrapped in a ScrollViewer. In my case I have a dynamic number of different datagrids that must display in a single view which can then be scrolled. As soon as I replace the ScrollViewer with A StackPanel the bug goes away, but I need the ScrollViewer.

Custom Button doesn't apply static resource correctly

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.

Is there a clean way to implement ancestor style triggers in XAML WPF

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.

How to highlight edited cell in a datagrid

How can I highlight a cell in DataGrid that has been edited? XAML solution through some style using triggers is preferable. But if not possible, then a code behind approach would be good enough.
I am not posting any code as I did not have any break through with the problem.
the answer is simply to create a style targeting DataGridCell and trigger the condition through binding, hopefully the steps below are easy to follow:
//lets say you bind datagrid to
List<RowValues> RowsView {get;}
//were RowValues is
List<RowValue> RowValues
// and RowValue is
public class RowValue
{
public bool IsEdited
{
get {return _isEdited;}
set
{
if(_isEdited== value) return;
_isEdited= value;
RaisePropertyChanged(()=>IsEdited);
}
}
public string Value
{
get {return _value;}
set
{
if(_value == value) return;
_value = value;
//check if the value is edited
IsEdited = _value == _originalValue;
RaisePropertyChanged(()=>Value);
}
}
}
//so in code accessing the structure would look like:
var row = RowView[0];
var cell = row[1];
cell.IsEdited... just to make it easier to see the XAML bindings below..
<DataGrid ItemsSource="{Binding RowsView}">
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding RowValues[0].IsEdited}" Value="True">
<Setter Property="Background" Value="{StaticResource MissingDataBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding RowValues[0].Value}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding RowValues[0].Value}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
....

Resources