Need direction for best way to minimize data template code in Xamarin form

87 Views Asked by At

In MVC ASP.net Core, I used partials to re-use blocks of a page. In Xamarin, we have DataTemplates & ControlTemplates but I'm not sure how to best use them.

In one of my pages I have the following for the content:

    <StackLayout>
        <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
            <Label Text="Welcome to data template selector" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
        </Frame>
        <CollectionView ItemsSource="{Binding MainPageView.Fields}"                        
                        EmptyView="No fields for this screen."
                        ItemTemplate="{StaticResource templateSelector}"
                        SelectionChanged="CollectionView_SelectionChanged">
        </CollectionView>
        <StackLayout Margin="10,0,10,5" Orientation="Vertical">
            <Button Command="{Binding MainPageView.SubmitCommand}" Text="Submit" />
            <validator:ErrorSummaryView 
                IsVisible="{Binding MainPageView.ShowValidationSummary, Mode=OneWay}"
                ErrorStateManager="{Binding MainPageView.ErrorStateManager, Mode=OneWay}"
                Margin="0,0,0,5"/>
        </StackLayout>
    </StackLayout>

The template selector is (there will be more choices later):

            <tempcel:FieldDataTemplateSelector
                x:Key="templateSelector"
                RadioTemplate="{StaticResource RadioTemplate}"
                DropListTemplate="{StaticResource DropListTemplate}">
            </tempcel:FieldDataTemplateSelector>

Where I could use some direction is right now 80% of what is in RadioTemplate and DropListTemplate are the same and I'd like to pull the shared code out so if I want to change the base layout, I only need to change one place. Here are the two DataTemplates:

            <DataTemplate x:Key="DropListTemplate">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <StackLayout 
                        Orientation="Horizontal"
                        Grid.Row="0">
                        <Label
                           Text="{Binding Name}"
                           Style="{StaticResource LabelStyle}">
                        </Label>
                        <ImageButton HorizontalOptions="Center" 
                                CornerRadius="6"
                                VerticalOptions="Center"
                                Clicked="HelpButton_Clicked"
                                HeightRequest="12"
                                WidthRequest="12"
                                BorderColor="Black"
                                BackgroundColor="Black"
                                BorderWidth="1"
                                IsVisible="{Binding ShowHelpButton}">
                            <ImageButton.Source>
                                <FontImageSource FontFamily="FAFreeSolid"
                                    Color="White"                                         
                                    Glyph="{x:Static fa:FontAwesomeIcons.Question}"/>
                            </ImageButton.Source>
                        </ImageButton>
                    </StackLayout>
                    <Label
                        Grid.Row="1"
                            Style="{StaticResource HelpStyle}"
                            Text="{Binding HelpTopic.Text}"
                            IsVisible="{Binding HelpTopic.IsVisible, Mode=TwoWay}">
                    </Label>
                    <Picker
                        Grid.Row="2"
                        IsEnabled="{Binding IsEnabled}"                        
                        Margin="10,2,10,0"
                        ItemsSource="{Binding Choices.Choices}"
                        SelectedItem="{Binding SelectedChoice}"
                        ItemDisplayBinding="{Binding Label}"                        
                        SelectedIndexChanged="Picker_SelectedIndexChanged">
                    </Picker>
                    <validator:ErrorView ErrorState="{Binding ErrorStatemanager[Input]}" Grid.Row="3" />
                </Grid>
            </DataTemplate>
            <DataTemplate x:Key="RadioTemplate">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <StackLayout 
                        Orientation="Horizontal"
                        Grid.Row="0">
                        <Label
                           Text="{Binding Name}"
                           Style="{StaticResource LabelStyle}">
                        </Label>
                        <ImageButton HorizontalOptions="Center" 
                                CornerRadius="6"
                                VerticalOptions="Center"
                                Clicked="HelpButton_Clicked"
                                HeightRequest="12"
                                WidthRequest="12"
                                BorderColor="Black"
                                BackgroundColor="Black"
                                BorderWidth="1"
                                IsVisible="{Binding ShowHelpButton}">
                            <ImageButton.Source>
                                <FontImageSource FontFamily="FAFreeSolid"
                                    Color="White"                                         
                                    Glyph="{x:Static fa:FontAwesomeIcons.Question}"/>
                            </ImageButton.Source>
                        </ImageButton>
                    </StackLayout>
                    <Label
                        Grid.Row="1"
                            Style="{StaticResource HelpStyle}"
                            Text="{Binding HelpTopic.Text}"
                            IsVisible="{Binding HelpTopic.IsVisible, Mode=TwoWay}">
                    </Label>
                    <StackLayout 
                        Grid.Row="2"
                        RadioButtonGroup.GroupName="{Binding Choices.Code}"
                        RadioButtonGroup.SelectedValue="{Binding Value}"
                        BindableLayout.ItemsSource="{Binding Choices.Choices}"
                        BindableLayout.EmptyView="No choices available"
                        Orientation="Horizontal"
                        Spacing="50"
                        Margin="10,2,0,0">
                        <BindableLayout.ItemTemplate>
                            <DataTemplate>
                                <RadioButton Value="{Binding Value}"
                                    Content="{Binding Label}"
                                    IsChecked="{Binding IsSelected}"
                                    CheckedChanged="OnRadioChanged">
                                </RadioButton>
                            </DataTemplate>
                        </BindableLayout.ItemTemplate>
                    </StackLayout>
                    <validator:ErrorView ErrorState="{Binding ErrorStatemanager[Input]}" Grid.Row="3" />
                </Grid>
            </DataTemplate>

I haven't figured out enough about Xamarin to know if I need to change where I have the CollectionView to put something there that has the common layout information with a way to put the different editors in. Or, if there is a way to modify the DataTemplates to get their base layout from something else. I tried looking at ContentPresenter but couldn't figure out how it would fit in.

Thanks

1

There are 1 best solutions below

2
Jessie Zhang -MSFT On

I found there is very little difference between DropListTemplate and RadioTemplate. So you can also achieve this without DropListTemplate and RadioTemplate . You can display and hide the two views (Picker and BindableLayout) based on the item data of the CollectionView 's ItemsSource.

The following are the difference in the two Templates:

            <Picker
                    Grid.Row="2"
                    IsEnabled="{Binding IsEnabled}"                        
                    Margin="10,2,10,0"
                    ItemsSource="{Binding Choices.Choices}"
                    SelectedItem="{Binding SelectedChoice}"
                    ItemDisplayBinding="{Binding Label}"                        
                    SelectedIndexChanged="Picker_SelectedIndexChanged">
            </Picker>

and

                <StackLayout 
                    Grid.Row="2"
                    RadioButtonGroup.GroupName="{Binding Choices.Code}"
                    RadioButtonGroup.SelectedValue="{Binding Value}"
                    BindableLayout.ItemsSource="{Binding Choices.Choices}"
                    BindableLayout.EmptyView="No choices available"
                    Orientation="Horizontal"
                    Spacing="50"
                    Margin="10,2,0,0">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <RadioButton Value="{Binding Value}"
                                Content="{Binding Label}"
                                IsChecked="{Binding IsSelected}"
                                CheckedChanged="OnRadioChanged">
                            </RadioButton>
                        </DataTemplate>
                    </BindableLayout.ItemTemplate>
                </StackLayout>