I would like to re use some Expanders
in a Xamarin.Forms app.
The Expander
uses Image
as FontImageSource
to display chevrons as Indicator
, and the DataTrigger
on the Image allows to switch between up/down chevron:
<Expander>
<Expander.Header>
<Grid>
<Label Text="Who we are?"
Style="{StaticResource AboutPageCategoryLabelStyle}" />
<Image
HeightRequest="20"
HorizontalOptions="End"
VerticalOptions="Center"
WidthRequest="20">
<Image.Source>
<FontImageSource
FontFamily="FontAwesomeLight"
Glyph="{StaticResource FalIconChevronDown}"
Size="20"
Color="Gray" />
</Image.Source>
<Image.Triggers>
<DataTrigger
Binding="{Binding Source={RelativeSource AncestorType={x:Type Expander}}, Path=IsExpanded}"
TargetType="Image"
Value="True">
<Setter Property="Source">
<Setter.Value>
<FontImageSource
FontFamily="FontAwesomeLight"
Glyph="{StaticResource FalIconChevronUp}"
Size="20"
Color="Gray" />
</Setter.Value>
</Setter>
</DataTrigger>
</Image.Triggers>
</Image>
</Grid>
</Expander.Header>
<Expander.ContentTemplate>
<DataTemplate>
...
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
I've tried to create a Style
to duplicate easily the same Expander
, but it doesn't work:
I can define the style of the Image
for the "default" indicator mode:
<Style x:Key="ChevronImageForExpander" TargetType="Image">
<Setter Property="BackgroundColor">Transparent</Setter>
<Setter Property="HorizontalOptions">End</Setter>
<Setter Property="VerticalOptions">Center</Setter>
<Setter Property="HeightRequest">20</Setter>
<Setter Property="WidthRequest">20</Setter>
<Setter Property="Source">
<Setter.Value>
<FontImageSource Glyph="{StaticResource FalIconChevronDown}"
FontFamily="FontAwesomeLight"
Size="20"
Color="{StaticResource Gray-600}"/>
</Setter.Value>
</Setter>
</Style>
Then in my View I apply this style:
<Expander>
<Expander.Header>
<Grid>
<Label Text="Header" />
<Image Style="{StaticResource ChevronImageForExpander}">
</Image>
</Grid>
</Expander.Header>
<Expander.ContentTemplate>
<DataTemplate>
<Grid>
<Label Text="Cotnent" />
</Grid>
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
This works fine, but I only have the "default" indicator image.
I've tried to define the style through a Trigger
for the "expanded" indicator mode:
<Style x:Key="ChevronImageForExpanderTrigger" TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={RelativeSource AncestorType={x:Type Expander}}, Path=IsExpanded}"
TargetType="Image"
Value="True">
<Setter Property="Source">
<Setter.Value>
<FontImageSource
FontFamily="FontAwesomeLight"
Glyph="{StaticResource FalIconChevronUp}"
Size="20"
Color="{StaticResource Gray-600}" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
This also works fine, but I only have the "expanded" indicator image.
So I've tried to "merge" the 2 styles like this:
<Style x:Key="ChevronImageForExpander" TargetType="Image">
<Setter Property="BackgroundColor">Transparent</Setter>
<Setter Property="HorizontalOptions">End</Setter>
<Setter Property="VerticalOptions">Center</Setter>
<Setter Property="HeightRequest">20</Setter>
<Setter Property="WidthRequest">20</Setter>
<Setter Property="Source">
<Setter.Value>
<FontImageSource Glyph="{StaticResource FalIconChevronDown}"
FontFamily="FontAwesomeLight"
Size="20"
Color="{StaticResource Gray-600}"/>
</Setter.Value>
</Setter>
<Setter Property="Triggers">
<Setter.Value>
<DataTrigger Binding="{Binding Source={RelativeSource AncestorType={x:Type Expander}}, Path=IsExpanded}"
TargetType="Image"
Value="True">
<Setter Property="Source">
<Setter.Value>
<FontImageSource
FontFamily="FontAwesomeLight"
Glyph="{StaticResource FalIconChevronUp}"
Size="20"
Color="{StaticResource Gray-600}" />
</Setter.Value>
</Setter>
</DataTrigger>
</Setter.Value>
</Setter>
</Style>
But this doesn't work and I get an Exception: "System.InvalidOperationException: The BindableProperty "Triggers" is readonly.".
I could also create a control, but I would like to use different kinds of content for the Expander.ContentTemplate
: labels, images, ...
How should be the better approach to easily reuse this Expander?
Edit: add some code for the Style
Finally it was just a problem of Trigger declaration in the "global" style: we must use <Style.Triggers>
instead of <Setter Property="Triggers">
So, like this it works well:
<Style x:Key="ChevronImageForExpander" TargetType="Image">
<Setter Property="BackgroundColor">Transparent</Setter>
<Setter Property="HorizontalOptions">End</Setter>
<Setter Property="VerticalOptions">Center</Setter>
<Setter Property="HeightRequest">20</Setter>
<Setter Property="WidthRequest">20</Setter>
<Setter Property="Source">
<Setter.Value>
<FontImageSource Glyph="{StaticResource FalIconChevronDown}"
FontFamily="FontAwesomeLight"
Size="20"
Color="{StaticResource Gray-600}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={RelativeSource AncestorType={x:Type Expander}}, Path=IsExpanded}"
TargetType="Image"
Value="True">
<Setter Property="Source">
<Setter.Value>
<FontImageSource
FontFamily="FontAwesomeLight"
Glyph="{StaticResource FalIconChevronUp}"
Size="20"
Color="{StaticResource Gray-600}" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
And in the XAML:
<Expander>
<Expander.Header>
<Grid>
<Label Text="Header" />
<Image Style="{StaticResource ChevronImageForExpander}">
</Image>
</Grid>
</Expander.Header>
<Expander.ContentTemplate>
<DataTemplate>
<Grid>
<Label Text="Content" />
</Grid>
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
Maybe is there another approach to apply ContentTemplate to the Header (both to the Label and to the Image), but at least, it's correct like this.