I am trying to create RadioButtons that bind to a list of content using a DataTemplate, and render based on a ControlTemplate. The data binding is working - I get a button for each element in the list. The VisualStateManager is also working - I get the requested state changes as I click on the buttons.
However, the ContentPresenter is not working - my buttons are empty. I'm also getting an InvalidCastException
each time I click on a button. Here is my code.
<ContentPage.BindingContext>
<pages:ActivitiesViewModel/>
</ContentPage.BindingContext>
<ContentPage.Resources>
<ControlTemplate x:Key="MuscleGroupButtonsTemplate">
<Border
Stroke="{StaticResource SecondaryBrush}"
StrokeThickness="1"
Background="Transparent"
>
<Border.StrokeShape>
<RoundRectangle CornerRadius="8"/>
</Border.StrokeShape>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter
Property="Background"
Value="{StaticResource AccentBrush}"/>
<Setter
Property="Stroke"
Value="{StaticResource SecondaryBrush}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter
Property="Background"
Value="{StaticResource NeutralBrush}"/>
<Setter
Property="Stroke"
Value="{StaticResource SecondaryBrush}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<ContentPresenter HeightRequest="64"/>
</Border>
</ControlTemplate>
</ContentPage.Resources>
<VerticalStackLayout Spacing="12"
RadioButtonGroup.GroupName="MuscleGroups"
RadioButtonGroup.SelectedValue="{Binding SelectedMuscleGroup}"
BindableLayout.ItemsSource="{Binding MuscleGroupList}">
<VerticalStackLayout.Resources>
<Style TargetType="RadioButton">
<Setter Property="ControlTemplate" Value="{StaticResource MuscleGroupButtonsTemplate}"/>
</Style>
</VerticalStackLayout.Resources>
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="m:MuscleGroup">
<RadioButton Value="{Binding Id}" CheckedChanged="OnMuscleGroupChanged">
<RadioButton.Content>
<HorizontalStackLayout Margin="12,6,0,0" Spacing="8">
<Image WidthRequest="64"
Aspect="AspectFit"
Source="{Binding Icon}"/>
<Label Style="{StaticResource Headline}" VerticalOptions="Center">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Name}"/>
</FormattedString>
</Label.FormattedText>
</Label>
</HorizontalStackLayout>
</RadioButton.Content>
</RadioButton>
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
I'm also puzzled because the Visual Tree shows the expected control hierarchy.
Oh, and BTW - my RadioButtonGroup.SelectedValue
is not working either.
I would appreciate any assistance. Thanks.
Chuck
With Content
part of ControlTemplate
and use of TemplateBinding Content.<property>
:
<ControlTemplate x:Key="RadioButtonControlTemplate">
<Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Property="Stroke" Value="Red"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter Property="Stroke" Value="Green"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<VerticalStackLayout x:DataType="m:NameId">
<Label Text="{TemplateBinding Content.Name}"/>
<Label Text="{TemplateBinding Content.Id}"/>
</VerticalStackLayout>
</Border>
</ControlTemplate>
VerticalStackLayout
:
<VerticalStackLayout
RadioButtonGroup.GroupName="NameIdGroup"
BindableLayout.ItemsSource="{Binding NameIdList}">
<VerticalStackLayout.Resources>
<Style TargetType="RadioButton">
<Setter Property="ControlTemplate"
Value="{StaticResource RadioButtonControlTemplate}"/>
</Style>
</VerticalStackLayout.Resources>
<BindableLayout.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding .}">
<RadioButton.GestureRecognizers>
<TapGestureRecognizer
Tapped="RadioButton_Tapped"
CommandParameter="{Binding .}" />
</RadioButton.GestureRecognizers>
</RadioButton>
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
NameId
class and ViewModel
:
public class NameId
{
public string Name { get; set; }
public string Id { get; set; }
}
public class ViewModel
{
public ObservableCollection<NameId> NameIdList { get; set; }
public ViewModel()
{
NameIdList = new ObservableCollection<NameId>
{
new NameId { Id = "Id A", Name = "Name A" },
new NameId { Id = "Id B", Name = "Name B" },
new NameId { Id = "Id C", Name = "Name C" }
};
}
}