Expander arrow image not updating with AppThemeBinding in Xamarin.Forms - xaml

If I try to make the arrow image for an expander change with system theme change, it doesn't change. The code below works perfectly, but the arrow image will be impossible to see if the app is in dark mode.
<xct:Expander>
<xct:Expander.Header>
<Grid>
<Label
FontAttributes="Bold"
FontSize="15"
Style="{StaticResource Label}"
Text="More Details" />
<Image
HeightRequest="25"
HorizontalOptions="End"
Source="DownArrow.png"
VerticalOptions="Start">
<Image.Triggers>
<DataTrigger
Binding="{Binding Source={RelativeSource AncestorType={x:Type xct:Expander}}, Path=IsExpanded}"
TargetType="Image"
Value="True">
<Setter Property="Source" Value="UpArrow.png" />
</DataTrigger>
</Image.Triggers>
</Image>
</Grid>
</xct:Expander.Header>
<Label
Text="Some content"
TextColor="{AppThemeBinding Light={StaticResource TextColor},
Dark=LightGray}" />
</xct:Expander>
If I try to make the make the arrow for the expander change with the system theme by doing {AppThemeBinding Light=DownArrow.png,Dark=DownArrowDark.png} and {AppThemeBinding Light=UpArrow.png,Dark=UpArrowDark.png} for image source, the image only changes from a down arrow to an up arrow on the first click then stays as an up arrow and doesn't update.

Rotate the image 180 degrees instead of replacing the source:
<Setter Property="Rotation" Value="180" />

Related

How Can I Reuse an Icon in Resources in UWP? In WPF, I'd use x:Shared=false

I am trying to create a button Style that I can use for a "Lookup" button throughout my UWP app. However, the icon only appears on the first button on the screen. I tried this solution using templates, but it is not working for me. Thanks for the help.
Code:
<Page.Resources>
<ControlTemplate x:Key="FindSymbolTemplate">
<SymbolIcon Symbol="Find" Foreground="White" />
</ControlTemplate>
<Style TargetType="Button" x:Key="LookupButton">
<Setter Property="Content">
<Setter.Value>
<ContentControl Template="{StaticResource FindSymbolTemplate}" />
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
....
<Button x:Name="tourNumLookup"
Style="{StaticResource LookupButton}"
Grid.Column="1"
Margin="10,0"
VerticalAlignment="Center" />
....
<Button x:Name="customerIdLookup"
Style="{StaticResource LookupButton}"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="1"
Margin="10,0" />
The two buttons in the UI. Only the first has the SymbolIcon content.
#Romasz's solution absolutely works, but what if you want a lightly different Foreground on the SymbolIcon inside another Button?
Here's a potentially more flexible way that I normally go with.
First let's create a base Style that holds some default values for all the icons.
<Style x:Key="Style-Icon-Base"
TargetType="ContentControl">
<!-- If you don't specify the Foreground, it will use its ancestor's -->
<!--<Setter Property="Foreground"
Value="White" />-->
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Width"
Value="20" />
<Setter Property="Height"
Value="20" />
<Setter Property="Padding"
Value="0" />
</Style>
Then we create a new icon Style which inherits from the one above. Note within the ControlTemplate I have used TemplateBinding to make property values dynamic. TemplateBinding isn't available inside a DataTemplate.
<Style x:Key="Style-Icon-Find"
BasedOn="{StaticResource Style-Icon-Base}"
TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<!--
'cause you cannot change the size of the SymbolIcon, we insert a Viewbox here,
otherwise you don't need it.
-->
<Viewbox Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<SymbolIcon Symbol="Find"
Foreground="{TemplateBinding Foreground}" />
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This way you have created a highly reusable icon Style, to use it, have a look at the following Buttons:
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<Button Margin="4"
Padding="8"
BorderBrush="LightBlue">
<ContentControl Width="36"
Height="36"
Foreground="DarkCyan"
Style="{StaticResource Style-Icon-Find}" />
</Button>
<!-- Note how I defined the Foreground at the Button level and it flows down to the icon -->
<Button Foreground="DarkGoldenrod"
Margin="4">
<StackPanel Orientation="Horizontal">
<ContentControl Style="{StaticResource Style-Icon-Find}"
Width="16"
Height="16" />
<TextBlock Text="Search"
VerticalAlignment="Center"
Margin="8,0,0,0" />
</StackPanel>
</Button>
<Button Margin="4"
Padding="4">
<ContentControl Style="{StaticResource Style-Icon-Find}" />
</Button>
</StackPanel>
And they look like:
Generally UI elements can be used once (or saying different - have only one parent) - this is probably why it only works for the first button in your case. One solution may be to define DataTemplate and use it as ContentTemplate, so each button creates its own icon:
<Page.Resources>
<DataTemplate x:Key="FindTemplate">
<SymbolIcon Symbol="Find" Foreground="White" />
</DataTemplate>
</Page.Resources>
...
<Button x:Name="tourNumLookup" ContentTemplate="{StaticResource FindTemplate}"
Grid.Column="1" Margin="10,0" VerticalAlignment="Center" />
<Button x:Name="customerIdLookup" ContentTemplate="{StaticResource FindTemplate}"
VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" Margin="10,0" />
You don't need to create ControlTemplate to reuse the icon. You can simply put this SymbolIcon to the resource dictionary and use as StaticResource for the buttons' Content.
<Page.Resources>
<SymbolIcon x:Key="FindSymbol" Symbol="Find" Foreground="White" />
</Page.Resources>
<Button x:Name="tourNumLookup"
Content="{StaticResource FindSymbol}"
Grid.Column="1"
Margin="10,0"
VerticalAlignment="Center" />
<Button x:Name="customerIdLookup"
Content="{StaticResource FindSymbol}"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="1"
Margin="10,0" />
UPDATE
BTW this is possibly a bug in the UWP platform, because I tried the following code and only the first Button rendered the icon at desing time and none of the at runtime.
<Page.Resources>
<SymbolIcon x:Key="FindSymbol" Symbol="Find" Foreground="White" />
<Style TargetType="Button" x:Key="LookupButton">
<Setter Property="Content" Value="{StaticResource FindSymbol}"/>
</Style>
</Page.Resources>
<StackPanel>
<Button x:Name="tourNumLookup"
Style="{StaticResource LookupButton}"
Margin="10,0"
VerticalAlignment="Center" />
<Button x:Name="customerIdLookup"
Style="{StaticResource LookupButton}"
VerticalAlignment="Center"
Margin="10,0" />
</StackPanel>
I tried to assign the Setter's Value directly but I got the same result. And also tried with FontIcon.

Button Menu flyout horizontal alignment in UWP

I need to set the menuflyout to get right aligned. I used the code, but it appears at left only. Should I need to modify in the style?
<Button Content="Click" HorizontalAlignment="Right" Height="30" Width="30">
<Button.Flyout>
<MenuFlyout Placement="Bottom">
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="MaxWidth" Value="50" />
<Setter Property="MaxHeight" Value="50" />
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
<MenuFlyoutItem Text="Item" />
</MenuFlyout>
</Button.Flyout>
</Button>
From the screenshot, it seems you are develpoing a Windows Phone 8.1 app not a UWP app.
While using UWP, your code (I remove Height and Width in the Button) looks like:
I think this is what you want.
But in Windows Phone 8.1, we have to modify the template of MenuFlyoutPresenter to achieve this.
To modify the template of MenuFlyoutPresenter, we can select the "[MenuFlyout]" in "Document Outline" and right click, then select "Edit Additional Templates" → "Edit MenuFlyoutPresenterStyle" → "Edit a Copy...".
In the template, we need to set the HorizontalAlignment of OuterBorder, CenterBorder and InnerBorder to Right:
<Border x:Name="OuterBorder" BorderBrush="{TemplateBinding BorderBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right">
...
<Border x:Name="CenterBorder" BorderBrush="{TemplateBinding Background}" FlowDirection="LeftToRight" HorizontalAlignment="Right">
<StackPanel x:Name="InnerBorder" Background="{TemplateBinding Background}" FlowDirection="{TemplateBinding FlowDirection}" HorizontalAlignment="Right">
...
</StackPanel>
</Border>
</Border>
Then in the Button, we can use code like following:
<Button HorizontalAlignment="Right" Content="Click">
<Button.Flyout>
<MenuFlyout MenuFlyoutPresenterStyle="{StaticResource MenuFlyoutPresenterStyle1}" Placement="Bottom">
<MenuFlyoutItem Text="Item" />
</MenuFlyout>
</Button.Flyout>
</Button>
It looks like:
You can also change other properties in the Style of MenuFlyoutPresenter to beautify it.
Actually if you use default settings and set your Placement property of MenuFlyout, position should look fine. When I modify your code it should work properly as what you need. Yıu can check from screenshot.
<Button Content="Click" HorizontalAlignment="Right" Height="30" Width="114" Margin="0,200,0,0" VerticalAlignment="Top" >
<Button.Flyout>
<MenuFlyout Placement="Bottom">
<MenuFlyoutItem Text="Item" HorizontalAlignment="Right" />
</MenuFlyout>
</Button.Flyout>
</Button>

WPF DocumentViewer control loses icons when changing template, how to show icons

I am tryng to add 2 new buttons to a document viewer control that us then hosted in a windows form, so I took the template from MSDN to modify, but the all the "inbuilt" standard buttons turn to text on display rather than the icons. I am wondering if anyone can please help me with why this happens and how to fix it as I have not been able to determine that from MSDN documentation. However I am a newbie to XAML. Below is the xaml for the modified control.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:Documents="clr-namespace:System.Windows.Documents;assembly=PresentationUI" x:Class="AddinXPSViewer.XPSBrowser"
xmlns:self="clr-namespace:AddinXPSViewer"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<Frame x:Name="DocFrame">
<Frame.Content>
<Grid>
<DocumentViewer x:Name="docViewer" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0,0,0,0" Unloaded="docViewer_Unloaded" Style="{DynamicResource DocumentViewerStyle}" ContextMenu="{x:Null}" >
<DocumentViewer.Resources>
<Style x:Key="DocumentViewerStyle" TargetType="DocumentViewer">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DocumentViewer">
<Grid KeyboardNavigation.TabNavigation="Local">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ToolBar
ToolBarTray.IsLocked="True"
KeyboardNavigation.TabNavigation="Continue">
<Button Command="ApplicationCommands.Copy"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Content="Copy"/>
<Separator />
<Button Command="NavigationCommands.IncreaseZoom"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Content="Zoom In"/>
<Button Command="NavigationCommands.DecreaseZoom"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Content="Zoom Out"/>
<Separator />
<Button Command="NavigationCommands.Zoom"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
CommandParameter="100.0"
Content="Actual Size" />
<Button Command="DocumentViewer.FitToWidthCommand"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Content="Fit to Width" />
<Button Command="DocumentViewer.FitToMaxPagesAcrossCommand"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
CommandParameter="1"
Content="Whole Page"/>
<Button Command="DocumentViewer.FitToMaxPagesAcrossCommand"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
CommandParameter="2"
Content="Two Pages"/>
<Button Command="self:XPSBrowserCustomCommands.Next">Previous</Button>
<Button Command="self:XPSBrowserCustomCommands.Previous">Next</Button>
</ToolBar>
<ScrollViewer Grid.Row="1"
CanContentScroll="true"
HorizontalScrollBarVisibility="Auto"
x:Name="PART_ContentHost"
IsTabStop="true"/>
<ContentControl Grid.Row="2"
x:Name="PART_FindToolBarHost"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DocumentViewer.Resources>
<DocumentViewer.CommandBindings>
<CommandBinding Command="ApplicationCommands.Print" Executed="CommandBinding_OnPrint" />
<CommandBinding Command="ApplicationCommands.Print" CanExecute="CommandBinding_CanExecutePrint" />
<CommandBinding Command="self:XPSBrowserCustomCommands.Next" Executed="CommandBinding_OnPrevious" />
<CommandBinding Command="self:XPSBrowserCustomCommands.Next" CanExecute="CommandBinding_CanExecutePrevious" />
<CommandBinding Command="self:XPSBrowserCustomCommands.Previous" Executed="CommandBinding_OnNext" />
<CommandBinding Command="self:XPSBrowserCustomCommands.Previous" CanExecute="CommandBinding_CanExecuteNext" />
</DocumentViewer.CommandBindings>
</DocumentViewer>
</Grid>
</Frame.Content>
</Frame>
</UserControl>
The secret is to right click and edit the Template or a copy of the Template twice in visual studio, this gives a different template to the one on msdn, and access to the sub controls for the toolbar.
On each Button the Content property is set to a string value.
e.g. Content="Copy"
If you want it to be an image you will have to set it to an Image control.
e.g.
<Button>
<Image Source="copy.png"/>
</Button>
The 'default templates' on MSDN are not the actual default templates from WPF. They are just sample code for making your own control template.

Flyout,Menu Flyout ,Combo Box occupy full screen in windows phone 8.1

I am developing an app in which combo box flyouts and menu flyouts are used ,But when I am using it , it occupy full screen in windows phone 8.1 ,Is this a default behavior or it can be controlled?
<Button.Flyout>
<Flyout Opened="Flyout_Opened">
<Flyout.FlyoutPresenterStyle>
<Style TargetType="FlyoutPresenter">
<Setter Property="Background" Value="#004469"></Setter>
</Style>
</Flyout.FlyoutPresenterStyle>
<StackPanel>
<TextBlock Foreground="White" Text="Create Text" FontSize="25" Margin="0,0,0,10" />
<TextBox x:Name="setText" Width="300" TextWrapping="Wrap"/>
<Button x:Name="addText" Background="#c0c0c0" Foreground="#004469" Content="Add" FontSize="20" Margin="0,10,0,10" Click="addText_Click"/>
</StackPanel>
</Flyout>
</Button.Flyout>
For example this occupy full screen.I need to control their width , How do I do that?
You can use this
XAML:
<MenuFlyout Placement="Top">
</MenuFlyout>
C#:
myMenuFlyout.Placement = FlyoutPlacementMode.Top;

How to make FlipView scrolling only one direction

A simple xaml like this
<FlipView>
<FlipView>
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
<Rectangle Fill="CornflowerBlue" />
<Rectangle Fill="CornflowerBlue" />
</FlipView>
<FlipView>
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
<Rectangle Fill="CornflowerBlue" />
<Rectangle Fill="CornflowerBlue" />
</FlipView>
<ListBox>
<Rectangle Fill="CornflowerBlue" />
<Rectangle Fill="CornflowerBlue" />
</ListBox>
</FlipView>
If the main FlipView's current item is a flipview,you can drag and scroll its item on two directions.But if it is a listbox,only one direction is available.means before your finger up,you cannot drag and scroll it on the other direction(Horizental or Vertical).
so how to make flipview's behavier as the same as listbox?
If you extract the default template from the FlipView you can see how the style has these setters:
<Setter
Property="ScrollViewer.IsHorizontalRailEnabled"
Value="False" />
<Setter
Property="ScrollViewer.IsVerticalRailEnabled"
Value="False" />
<Setter
From that you can deduce that setting ScrollViewer.IsHorizontalRailEnabled and ScrollViewer.IsVerticalRailEnabled on your FlipView to True gives you want you ask for.