reusable template

Eduardo Gomez Romero 845 Reputation points
2024-09-25T16:38:02.9433333+00:00

In my collectionView, I have this

 <CollectionView
     Margin="20"
     ItemsSource="{Binding Turbines}">
     <CollectionView.ItemTemplate>
         <DataTemplate x:DataType="model:TurbinePin">
             
             <!-- Use SwipeView for mobile -->
             
             <OnIdiom x:TypeArguments="View">
                 <OnIdiom.Phone>
                     <SwipeView>
                         <SwipeView.RightItems>
                             <SwipeItems>
                                 <SwipeItem Text="Delete"
                                            BackgroundColor="Red"
                                            Command="{Binding Source={x:RelativeSource AncestorType={x:Type vm:TurbinesCollectionPageViewModel}}, Path=DeleteTurbineCommand}"
                                            CommandParameter="{Binding Turbine}">
                                     <SwipeItem.IconImageSource>
                                         <FontImageSource Glyph="{x:Static constant:MaterialFonts.Delete}"
                                                          FontFamily="ma" />
                                     </SwipeItem.IconImageSource>
                                 </SwipeItem>
                             </SwipeItems>
                         </SwipeView.RightItems>

                         <Border>
                             <Border.StrokeShape>
                                 <RoundRectangle CornerRadius="8" />
                             </Border.StrokeShape>
                             <Grid Padding="10"
                                   ColumnDefinitions="*,30"
                                   RowDefinitions="*,*">
                                 <Label Text="{Binding Turbine.Name}" />
                                 <Label Grid.Row="1"
                                        Text="{Binding Turbine.Address}" />
                                 <Label Grid.RowSpan="2"
                                        Grid.Column="1"
                                        FontFamily="ma"
                                        FontSize="Medium"
                                        HorizontalTextAlignment="End"
                                        Text="{x:Static constant:MaterialFonts.Info}"
                                        VerticalTextAlignment="Center" />
                             </Grid>
                         </Border>
                     </SwipeView>
                 </OnIdiom.Phone>

                 <OnIdiom.Desktop>

                     <Border>
                         <Border.StrokeShape>
                             <RoundRectangle CornerRadius="8" />
                         </Border.StrokeShape>
                         <Grid Padding="10"
                               ColumnDefinitions="*,30"
                               RowDefinitions="*,*">
                             <Label Text="{Binding Turbine.Name}" />
                             <Label Grid.Row="1"
                                    Text="{Binding Turbine.Address}" />
                             <Label Grid.RowSpan="2"
                                    Grid.Column="1"
                                    FontFamily="ma"
                                    FontSize="Medium"
                                    HorizontalTextAlignment="End"
                                    Text="{x:Static constant:MaterialFonts.Info}"
                                    VerticalTextAlignment="Center" />
                             
                             <!-- Delete button for desktop -->

                             <Button Grid.Column="1"
                                     Command="{Binding Source={x:RelativeSource AncestorType={x:Type vm:TurbinesCollectionPageViewModel}}, Path=DeleteTurbineCommand}"
                                     CommandParameter="{Binding Turbine}"
                                     VerticalOptions="Center"
                                     HorizontalOptions="End">
                                 <Button.ImageSource>
                                     <FontImageSource Glyph="{x:Static constant:MaterialFonts.Delete}"
                                                      FontFamily="ma" />
                                 </Button.ImageSource>
                             </Button>
                         </Grid>
                     </Border>
                 </OnIdiom.Desktop>
             </OnIdiom>
         </DataTemplate>
     </CollectionView.ItemTemplate>
 </CollectionView>


As you can see I am duplicating this

                        <Border>
                             <Border.StrokeShape>
                                 <RoundRectangle CornerRadius="8" />
                             </Border.StrokeShape>
                             <Grid Padding="10"
                                   ColumnDefinitions="*,30"
                                   RowDefinitions="*,*">
                                 <Label Text="{Binding Turbine.Name}" />
                                 <Label Grid.Row="1"
                                        Text="{Binding Turbine.Address}" />
                                 <Label Grid.RowSpan="2"
                                        Grid.Column="1"
                                        FontFamily="ma"
                                        FontSize="Medium"
                                        HorizontalTextAlignment="End"
                                        Text="{x:Static constant:MaterialFonts.Info}"
                                        VerticalTextAlignment="Center" />
                             </Grid>

I am also duplicating the deleteCommand and the fontImageSource

the only diferene is that in phones, I have a swipe and desktop a button with an icon

so how can I reduce this ode as much as posible

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,596 questions
{count} votes

Accepted answer
  1. Wenyan Zhang (Shanghai Wicresoft Co,.Ltd.) 32,386 Reputation points Microsoft Vendor
    2024-10-03T08:57:46.96+00:00

    Hello,

    I double-check the xaml code snippets you provided. On the view on phone, you added the swipe view (and a grid) without the delete button. On the view on desktop, there is Grid wrapping the label.

    The structure of views varies greatly, and the reusable part is the following:

     <Label Text="{Binding Turbine.Name}" />
                         <Label
                             Grid.Row="1"
                             Text="{Binding Turbine.Address}" />
                         <Label
                             Grid.Row="2"
                             Text="{Binding Turbine.LocalizedInstalationDateTime}" />
    

    It's not very necessary to recuse the template. If you still want to recuse these three labels, you should create a custom control with bindable properties. And you could refer to the following code:

    Custom Grid

    <Grid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="ReuseCollectionview.CustomGrid"
          x:Name="this">
     
        <Grid BindingContext="{x:Reference this}"
            Padding="10"
                                       ColumnDefinitions="*,30"
                                       RowDefinitions="*,*">
    <Label Text="{Binding Name}" />
    <Label Grid.Row="1"
                                            Text="{Binding Address}" />
    <Label Grid.RowSpan="2"
                                            Grid.Column="1"
                                            FontFamily="ma"
                                            FontSize="Medium"
                                            HorizontalTextAlignment="End"
                                            Text="x:Static constant:MaterialFonts.Info"
                                            VerticalTextAlignment="Center" />
    </Grid>
     
    </Grid>
    
    public partial class CustomGrid : Grid
    {
        public static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(CustomGrid), string.Empty);
        public static readonly BindableProperty AddressProperty = BindableProperty.Create(nameof(Address), typeof(string), typeof(CustomGrid), string.Empty);
        public string Name
        {
            get => (string)GetValue(NameProperty);
            set => SetValue(NameProperty, value);
        }
     
        public string Address
        {
            get => (string)GetValue(AddressProperty);
            set => SetValue(AddressProperty, value);
        }
     
        public CustomGrid()
    	{
    		InitializeComponent();
    	}
    }
    
    

    usage

    <local:CustomGrid Name="{Binding Turbine.Name}" Address="{Binding Address}"></local:CustomGrid>
    

    If you want to wrapper the whole view (Swipe view/Grid) or the whole DataTemplate, please feel free to let me know, we can work together to figure it out.

    Update


    I understand that you want to use the DataTemplateSelector to choose the template, please refer to the following:

    public class ChooseDataTemplateSelector : DataTemplateSelector
      {
          public DataTemplate PhoneTemplate { get; set; }
     
          public DataTemplate DeskTopTemplate { get; set; }
     
          protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
          {
              return (DeviceInfo.Current.Idiom == DeviceIdiom.Desktop)? DeskTopTemplate : PhoneTemplate;
          }
      }
    

    The page (Xaml)

    <ContentPage ...
                 xmlns:local ="XXX">
     
        <ContentPage.Resources>
    <DataTemplate x:Key="PhoneTemplate">
    <SwipeView >
     ...// your view on phone
    </SwipeView>
    </DataTemplate>
    <DataTemplate x:Key="DeskTopTemplate">
    <Border>
    // your view on desktop
    </Border>
    </DataTemplate>
    <local:ChooseDataTemplateSelector x:Key="SelectDataTemplateSelector"
                                              PhoneTemplate="{StaticResource PhoneTemplate}"
                                              DeskTopTemplate="{StaticResource DeskTopTemplate}" />
    </ContentPage.Resources>
     
        <CollectionView
         Margin="20"
         ItemsSource="{Binding Turbines}" ItemTemplate="{StaticResource SelectDataTemplateSelector}">
    </CollectionView>
     
    </ContentPage>
    

    Best Regards,

    Wenyan Zhang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


1 additional answer

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.