Reputation: 5395
Here is my CollectionView:
<CollectionView
Margin="5,5,5,15"
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding Languages}"
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"
SelectionChangedCommand="{Binding LanguageChangedCommand}"
SelectionMode="Single">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="language:CultureInfo">
<ContentView Padding="5" >
<Grid ColumnDefinitions="*,3*">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Image Source="{Binding TwoLetterISOLanguageName, StringFormat='flag_{0}.png'}" Grid.Column="0" HorizontalOptions="Start" />
<Label Text="{Binding DisplayName}" Grid.Column="1" HorizontalOptions="Start" VerticalOptions="Center" />
</Grid>
</ContentView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
And here is my style:
<Style TargetType="ContentView">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource LaticreteColor}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
Here I set background color of the selected item. But I also need to set text color of the selected item, and TextColor property does not exist:
"Cannot resolve property "TextColor" on type "ContentView (property missing or missing accessors)"."
How can this be achieved?
Upvotes: 0
Views: 356
Reputation: 10148
To achieve the effect, you can use VisualStateManager.VisualStateGroups
to make it work. Please try adding x:Name
for the Label and then use to set the TextColor
for the Label. See Set state on multiple elements.
Please refer to the sample code below:
<ContentPage.Resources>
<Style TargetType="ContentView">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Yellow" />
<Setter TargetName="label" Property="Label.TextColor" Value="Red" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectionChanged="OnCollectionViewSelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<ContentView Padding="5">
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
x:Name="label"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</ContentView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Output:
Upvotes: 1
Reputation: 26149
The solution would be to put a VisualStateGroup
directly on your DataTemplate
in the areas you need it, so, you can put one directly on the ContentView
for the BackgroundColor
but, you can also put one directly on the Label
for TextColor
.
However, I found a quirk/bug with CollectionView
not showing the VisualGroup correctly on startup. Only after you've interacted with the CollectionView
do you see the outcome, hence, any initial value in the SelectedLanguages
will not be shown to the user.
There are two workarounds needed to resolve that issue:
SelectedLanguages
VisualStateGroup
with a Binding
(or MultiBinding
).Here, I've used a simplistic CompareToObjectConverter
. You'll see that this has been hardcoded to only recognize strings, but, you can generalize for other types:
public class CompareToObjectConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length != 4)
throw new ArgumentException("Must have four values");
return values[0]?.ToString() == values[1]?.ToString() ? values[2] : values[3];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then, in your XAML, you can refer to this converter in your Bindings
:
<!-- MainPage.xaml ... -->
<ContentPage>
<!-- ... -->
<ContentPage.Resources>
<ResourceDictionary>
<local:CompareToObjectConverter x:Key="CompareToObjectConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
<!-- ... -->
<CollectionView ItemsSource="{Binding Languages}"
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<ContentView>
<ContentView.BackgroundColor>
<MultiBinding Converter="{x:StaticResource CompareToObjectConverter}">
<Binding Path="SelectedLanguage.Name" Source="{x:RelativeSource AncestorType={x:Type local:MainPage}}"/>
<Binding Path="Name"/>
<Binding Path="." Source="{x:Static Colors.LightSteelBlue}"/>
<Binding Path="." Source="{x:Static Colors.Transparent}"/>
</MultiBinding>
</ContentView.BackgroundColor>
<Grid ColumnDefinitions="*,*">
<Image Source="{Binding TwoLetterISOLanguageName, StringFormat='flag_{0}.png'}"/>
<Label Grid.Column="1" Text="{Binding DisplayName}">
<Label.TextColor>
<MultiBinding Converter="{x:StaticResource CompareToObjectConverter}">
<Binding Path="SelectedLanguage.Name" Source="{x:RelativeSource AncestorType={x:Type local:MainPage}}"/>
<Binding Path="Name"/>
<Binding Path="." Source="{x:Static Colors.White}"/>
<Binding Path="." Source="{x:Static Colors.Black}"/>
</MultiBinding>
</Label.TextColor>
</Label>
</Grid>
</ContentView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
Upvotes: 1