Xamarin Forms how to apply SVG to a button data triggers? - xamarin

So my app needs SVGs now or I want to switch png to svg so it can scale well with difference screen sizes. I know I can draw svg using <Path> but <Path> doesn't have data triggers but they do have GestureRecognizers which is useful but without data triggers idk how else to achieve what I want.
This is my current xaml for a button to data trigger and switch its content depending on playing state of a MediaElement. I would like to switch the Text to a SVG of play pause images.
<Button x:Name="OnPlayPauseButtonClicked"
Grid.Row="1"
Text="▶️ Play"
VerticalOptions="End"
Clicked="OnPlayPauseButton_Clicked">
<Button.Triggers>
<DataTrigger TargetType="Button"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Playing}">
<Setter Property="Text"
Value="⏸ Pause"/>
</DataTrigger>
<DataTrigger TargetType="Button"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Buffering}">
<Setter Property="IsEnabled"
Value="False"/>
</DataTrigger>
</Button.Triggers>
</Button>
I have tried putting my play and pause svg files into drawable folder and apply the Value to property of ImageSource. That didn't work. I then tried converting the SVG to XML and use the instead and it didn't work.
Is there a way to do this without using any dependencies?
Thanks in advance.

You have a few options here:
1. Font Icons
There is a much better way to accomplish what you are trying to do using Font Icons, e.g. Material Design Icons. Here is a cheat sheet for the icons.
This is not strictly a dependency, if you add the fonts as a resource (which you need to do in either case using PNGs, SVGs or - in this case - an image font).
<Button x:Name="OnPlayPauseButtonClicked" Grid.Row="1" Text="󰐊" VerticalOptions="End" Clicked="OnPlayPauseButton_Clicked"
FontFamily="materialdesignicons">
<Button.Triggers>
<DataTrigger TargetType="Button"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Playing}">
<!-- Pause Button Icon -->
<Setter Property="Text" Value="󰏤"/>
</DataTrigger>
<DataTrigger TargetType="Button"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Paused}">
<!-- Play Button Icon -->
<Setter Property="Text" Value="󰐊"/>
</DataTrigger>
<DataTrigger TargetType="Button"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Buffering}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Button.Triggers>
</Button>
James Montemagno also has a great blog post on this: https://montemagno.com/using-font-icons-in-xamarin-forms-goodbye-images-hello-fonts/
2. ImageButton
You can add your images to your project's resources and load them into an ImageButton. How to use ImageButtons refer to this link: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/imagebutton.
SVGs
There is a library that allows you to load SVGs, this will require the following nuget to be installed: https://github.com/luberda-molinet/FFImageLoading/
<ImageButton x:Name="OnPlayPauseButtonClicked" Grid.Row="1" VerticalOptions="End" Clicked="OnPlayPauseButton_Clicked">
<ImageButton.Triggers>
<DataTrigger TargetType="ImageButton"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Playing}">
<!-- Pause Button Icon -->
<Setter Property="Source">
<Setter.Value>
<ffimageloadingsvg:SvgCachedImage Source="resource://YourAppName.Resources.Pause.svg"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger TargetType="ImageButton"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Paused}">
<!-- Play Button Icon -->
<Setter Property="Source">
<Setter.Value>
<ffimageloadingsvg:SvgCachedImage Source="resource://YourAppName.Resources.Play.svg"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger TargetType="ImageButton"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Buffering}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</ImageButton.Triggers>
</ImageButton>
PNGs
To see how to add images to your app, refer to this page: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/images?tabs=windows#embedded-images
<ImageButton x:Name="OnPlayPauseButtonClicked" Grid.Row="1" VerticalOptions="End" Clicked="OnPlayPauseButton_Clicked">
<ImageButton.Triggers>
<DataTrigger TargetType="ImageButton"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Playing}">
<!-- Pause Button Icon -->
<Setter Property="Source" Value="{local:ImageResource Pause.PNG}" />
</DataTrigger>
<DataTrigger TargetType="ImageButton"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Paused}">
<!-- Play Button Icon -->
<Setter Property="Source" Value="{local:ImageResource Play.PNG}" />
</DataTrigger>
<DataTrigger TargetType="ImageButton"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Buffering}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</ImageButton.Triggers>
</ImageButton>
[Update] 3: Use SvgCachedImage directly
You can also use SvgCachedImage directly instead of a Button and attach a TapGestureRecognizer to it:
<ffimageloadingsvg:SvgCachedImage x:Name="OnPlayPauseButtonClicked" Grid.Row="1" VerticalOptions="End">
<ffimageloadingsvg:SvgCachedImage.Triggers>
<DataTrigger TargetType="ffimageloadingsvg:SvgCachedImage"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Playing}">
<!-- Pause Button Icon -->
<Setter Property="Source"
Value="resource://YourAppName.Resources.Pause.svg"/>
</DataTrigger>
<DataTrigger TargetType="ffimageloadingsvg:SvgCachedImage"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Paused}">
<!-- Play Button Icon -->
<Setter Property="Source"
Value="resource://YourAppName.Resources.Play.svg"/>
</DataTrigger>
<DataTrigger TargetType="ffimageloadingsvg:SvgCachedImage"
Binding="{Binding CurrentState}"
Value="{x:Static xct:MediaElementState.Buffering}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</ffimageloadingsvg:SvgCachedImage.Triggers>
<ffimageloadingsvg:SvgCachedImage.GestureRecognizers>
<TapGestureRecognizer Tapped="OnPlayPauseButton_Clicked"/>
</ffimageloadingsvg:SvgCachedImage.GestureRecognizers>
</ffimageloadingsvg:SvgCachedImage>

You can use SkiaSharp to draw patterns, create custom controls to load it. For drawing patterns, refer to this document. The answer to this issue can also help you.

Related

How to center a text to a RadioButton with ControlTemplate in Xamarin

I was trying to use ControlTemplate to make a custom RadioButton that doesn't have the little circle, but now I can't center the text to be in the middle, how could I center it, and I'm trying to use every way I can think of.
The code of the ControlTemplate I tried to use
<ControlTemplate x:Key="RadioButtonTemplate">
<Frame
Padding="0"
BackgroundColor="#D9D9D9"
BorderColor="#877373"
HasShadow="False"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="400"
CornerRadius="20"
>
<Grid Margin="4" WidthRequest="240">
Here is a small code that hides the circles
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Property="BorderColor" Value="#df6e57" />
<Setter Property="Padding" Value="5"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="HorizontalOptions" Value="Center"/>
<Setter TargetName="Check" Property="Opacity" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter Property="BorderColor" Value="#F3F2F1" />
<Setter Property="Padding" Value="5"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="HorizontalOptions" Value="Center"/>
<Setter TargetName="Check" Property="Opacity" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
</Frame>
</ControlTemplate>
You can check the doc. And you can set it like this:
<RadioButton>
<RadioButton.Content>
<StackLayout>
<Label Text="xxx"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</RadioButton.Content>
</RadioButton>

Change background color of selected item in CollectionView not working on UWP

I want to change the background color of the selected item. I have tried the following solution but it didn't work.
<CollectionView x:Name="FlexCategoryType" Margin="0" HorizontalOptions="FillAndExpand" SelectionMode="Single" ItemsSource="{Binding ItemsCategory}" SelectedItem="{Binding SelectedCategory, Mode=TwoWay}" SelectionChanged="FlexCategoryType_SelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Yellow" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
CollectionView SelectedItem is not highlighted in Xamarin Forms
Change background color of selected item in CollectionView not working on UWP
The problem is that you have not specific CollectionView SelectionMode, the default value is none. Please set it as Single. and add VisualStateGroups like the following
<CollectionView SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Margin="10">
<Label Text="{Binding}" VerticalOptions="Center" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Yellow" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>1</x:String>
<x:String>2</x:String>
<x:String>3</x:String>
<x:String>4</x:String>
<x:String>5</x:String>
</x:Array>
</CollectionView.ItemsSource>
</CollectionView>
Update
How to change ListView Cell selected color.
Here is FormsListViewItem style, please copy it to UWP App.xaml file and edit SelectedBackground as you want color.
For example
<Application.Resources>
<ResourceDictionary>
<Style x:Key="FormsListViewItem" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="IsHoldingEnabled" Value="True" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter
CheckBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
ContentMargin="{TemplateBinding Padding}"
CheckMode="Inline"
ContentTransitions="{TemplateBinding ContentTransitions}"
CheckBoxBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
FocusBorderBrush="{ThemeResource SystemControlForegroundAltHighBrush}"
FocusSecondaryBorderBrush="{ThemeResource SystemControlForegroundBaseHighBrush}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
PointerOverForeground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
PressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
PointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
SelectedPressedBackground="{ThemeResource SystemControlHighlightListAccentHighBrush}"
SelectionCheckMarkVisualEnabled="True"
SelectedForeground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
SelectedPointerOverBackground="{ThemeResource SystemControlHighlightListAccentMediumBrush}"
SelectedBackground="SeaGreen"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>

Change windowStyle of Prism Dialogwindow

How can I change the window style dynamically via Trigger?
Like:
<Style TargetType="UserControl">
<Setter Property="prism:Dialog.WindowStyle" Value="{DynamicResource DefaultDialogStyleTheme}"></Setter>
<Style.Triggers>
<DataTrigger
Binding="{Binding SecondOne, UpdateSourceTrigger=PropertyChanged}"
Value="true">
<Setter Property="prism:Dialog.WindowStyle" Value="{DynamicResource DialogStyleTheme}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>`
You can register your own IDialogWindow implementation that has all the styles you desire.
The library's implementation's code's here (xaml) and there (code-behind) as a reference.
Thanks for your help :), But for example before we switched to new Prism, we've used a PopupWindowAction to raise a default window or a custom window:
var wrapperWindow = GetWindow(args.Context);
wrapperWindow.ShowDialog();
GetWindow returns a Window or CustomWindowObject.
That's the custom window style:
<Style x:Key="DialogStyleTheme" TargetType="implementation:CustomDialogWindow">
<Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="CanMinimize" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="FontSize" Value="60" />
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="implementation:CustomDialogWindow">
<Border BorderThickness="2" CornerRadius="10" BorderBrush="White" Background="DimGray"
x:Name="MainBorder">
<Grid Background="{TemplateBinding Background}" Margin="5,5,5,5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="30" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="MoveGrid">
<Image x:Name="Image">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Stretch" Value="UniformToFill" />
<Style.Triggers>
<DataTrigger Binding="{Binding SmallTitle}" Value="true">
<Setter Property="Height" Value="40" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Text="{Binding Title}">
<TextBlock.Style>
<Style BasedOn="{StaticResource TouchHeadTextBlock}" TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding SmallTitle}" Value="true">
<Setter Property="FontSize" Value="25" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<ContentPresenter Grid.Row="2" x:Name="ContentPresenter" ClipToBounds="True" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I'm setting the WindowStyle in my UserControl and I want to change this style via trigger....
prism:Dialog.WindowStyle="{DynamicResource DialogStyleTheme}"
Initialization:
containerRegistry.RegisterDialog<ItemSelectionDialogView, ItemSelectionDialogViewModel>();
containerRegistry.RegisterDialogWindow<CustomDialogWindow>();

How to choose my image according to the windows phone theme in xaml

In my xaml code I have this:
<Button Grid.ColumnSpan="2" Grid.Row="3" Height="72" Name="btnSend" Click="btnSend_Click">
<Button.Background>
<ImageBrush x:Name="imButton" ImageSource="/icons/appbar.feature.email.rest.png" Stretch="None"/>
</Button.Background>
</Button>
For the imageSource I use a default icon from sdk, my problem is when I change de theme in light, the icon doesn't change and stay white. How to change this image when changing theme?
You can using transparent for solving this problem.
First, create a style for this button:
<phone:PhoneApplicationPage.Resources>
<Style x:Key="IconButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Padding" Value="10,3,10,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">
<Grid x:Name="ContentContainer" OpacityMask="{TemplateBinding Content}" Background="{TemplateBinding Foreground}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
after that use it as following:
<Button Style="{StaticResource IconButton}" >
<ImageBrush ImageSource="/icons/home.png">
</Button>
more info try find here
Automatic conversion of button image colors is only done on the AppBar. For all other iamges you'll have to do the test yourself.
Something like this will work:
var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible;
You can then use that boolean to determine which image to show. Having a standard naming convention for the different version of each image is probably recommended and this will make it easier to work with a converter.
You just need using "white" icon. You can find it in Microsoft SDKs\Windows Phone\v7.1\Icons\dark

How can I make something like this? (Tiles inside the app) Windows phone

I'm sorry if the question title wasnt clear, but I'm trying to make something like this. I don't know if they are tiles or images inside a WrapControl:
I was thinking of making such thing with a wrap panel and each one of those blocks as a stackpanel. but I'm not sure if thats the right approach.
is there a control to do such thing?
You are on the right track. WrapPanel is the way to go :)
To make each block more interesting, you can take a look at the HubTile control from the latest windows phone toolkit. Whatever controls/panels you are using, just remember the size should be 173*173.
Use a ListBox
In one of my projects I created a ListBox that does all this. The reason that I use a ListBox is because ListBox has a SelectedItem propery which tells me which tile is tapped by the user. Also another reason is ListBoxItems can receive the nice tilt effect.
Baiscally you just need to create a tile-like ListBoxItem style and apply it to the ListBox's ItemContainerStyle, also you need to set the ListBox's ItemsPanel to be a WrapPanel.
How it looks
The ListBoxItem Style
<Style x:Key="TileListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="FontSize" Value="64"/>
<Setter Property="Margin" Value="12,12,0,0"/>
<Setter Property="Background" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="173"/>
<Setter Property="Height" Value="173"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Rectangle Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The ListBox
<!-- set its ItemContainerStyle which is the style for each ListBoxItem -->
<ListBox ItemContainerStyle="{StaticResource TileListBoxItemStyle}">
<!-- set its ItemsPanel to be a WrapPanel -->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>
<Grid>
<TextBlock Text="Messages" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Data="M1.4901163E-05,9.8579922 L50.000015,46.316994 L100.00002,9.8579922 L100.00002,62.499992 L1.4901163E-05,62.499992 z M0,0 L100,0 L50,36.458 z" Fill="White" Height="38.125" Stretch="Fill" UseLayoutRounding="False" Width="61" d:IsLocked="True" />
<TextBlock Text="12" Margin="4,0,0,8" />
</StackPanel>
</Grid>
</ListBoxItem>
<ListBoxItem/>
<ListBoxItem/>
<ListBoxItem/>
<toolkit:HubTile Title="Me ☺" Message="..." Notification="new messages!" Source="xxx.jpg" Margin="12,12,0,0" />
</ListBox>
You can see the last item is actually a HubTile.
Hope ths helps! :)

Resources