Xamarin Forms, Dynamic ScrollView en XAML

Sep 12 2020

Je veux créer une interface graphique qui a un similaire à ce que le code suivant génère, un défilement de cadres.

Cependant, je veux pouvoir avoir un défilement de cadres de contenu dynamique, idéalement en XAML et remplis avec une source d'élément. Je ne pense pas que cela soit possible sans créer une vue personnalisée basée sur la vue des éléments d'après ce que je peux voir. ListView et CollectionView ne font pas tout à fait ce que je veux.

Je pense que j'ai besoin d'utiliser l'aperçu CarouselView, je me demandais s'il y avait un moyen de faire ce que je cherche sans.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FlexTest.MainPage">

    <ContentPage.Resources>
    <Style TargetType="Frame">
        <Setter Property="WidthRequest" Value="300"/>
        <Setter Property="HeightRequest" Value="500"/>
        <Setter Property="Margin" Value="10"/>
        <Setter Property="CornerRadius" Value="20"/>
    </Style>
    </ContentPage.Resources>
    
    
    <ScrollView Orientation="Both">
        <FlexLayout>
            <Frame BackgroundColor="Yellow">
                <FlexLayout Direction="Column">
                    <Label Text="Panel 1"/>
                    <Label Text="A Panel"/>
                    <Button Text="Click Me"/>
                </FlexLayout>
            </Frame>
            <Frame BackgroundColor="OrangeRed">
                <FlexLayout Direction="Column">
                    <Label Text="Panel 2"/>
                    <Label Text="Another Panel"/>
                    <Button Text="Click Me"/>
                </FlexLayout>
            </Frame>
            <Frame BackgroundColor="ForestGreen">
                <FlexLayout Direction="Column">
                    <Label Text="Panel 3"/>
                    <Label Text="A Third Panel"/>
                    <Button Text="Click Me"/>
                </FlexLayout>
            </Frame>
        </FlexLayout>
    </ScrollView>
</ContentPage>

Merci Andy.

Réponses

1 JarvanZhang-MSFT Sep 14 2020 at 15:26

Voulez-vous implémenter une vue défilante et chaque enfant contient plusieurs contenus qui peuvent faire défiler horizontalement?

Pour cette fonctionnalité, essayez d'afficher le CarouselViewdans un fichier ListView.

Vérifiez le code:

<ListView ...>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <CarouselView>
                    <CarouselView.ItemTemplate>
                        <DataTemplate>
                            ...
                        </DataTemplate>
                    </CarouselView.ItemTemplate>
                </CarouselView>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Tutoriel sur CarouselView:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/carouselview/introduction

1 SomeStudent Sep 12 2020 at 10:12

Préface: j'espère avoir bien compris votre demande :)

Si par contenu dynamique vous entendez avoir un ItemTemplate dynamique, vous pouvez essayer de faire ce qui suit:

La première étape:

Définissez un ItemTemplateSelector, vous pouvez lui donner le nom que vous voulez. Dans cette classe, nous définirons le type de modèles que nous avons, disons que nous avons les trois que vous avez définis: Jaune, OrangeRed, ForestGreen

   public class FrameTemplateSelector : DataTemplateSelector {
       public DataTemplate YellowFrameTemplate {get; set;}
       public DataTemplate OrangeRedFrameTemplate {get; set;}
       public DataTemplate ForestGreenFrameTemplate {get; set;}

       public FrameTemplateSelector() {
          this.YellowFrameTemplate = new DataTemplate(typeof (YellowFrame));
          this.OrangeRedFrameTemplate = new DataTemplate(typeof (OrangeRedFrame));
          this.ForestGreenFrameTemplate = new DataTemplate(typeof (ForestGreenFrame));
       }

       //This part is important, this is how we know which template to select.
       protected override DataTemplate OnSelectTemplate(object item, BindableObject container) {
          var model = item as YourViewModel;
          switch(model.FrameColor) {
            case FrameColorEnum .Yellow:
              return YellowFrameTemplate;
            case FrameColorEnum .OrangeRed:
              return OrangeRedFrameTemplate;
            case FrameColorEnum .ForestGreen:
              return ForestGreenFrameTemplate;
            default:
             //or w.e other template you want.
              return YellowFrameTemplate;
       }
   }

Deuxième étape:

Maintenant que nous avons défini notre sélecteur de modèle, allons-y et définissons nos modèles, dans ce cas nos cadres Jaune, OrangeRed et ForestGreen respectivement. Je vais simplement montrer comment faire l'un d'eux puisque les autres suivront le même paradigme en excluant, avec bien sûr le changement de couleur. Faisons le YellowFrame

Dans le XAML, vous aurez:

YellowFrame.xaml:

<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         mc:Ignorable="d"
         x:Class="YourNameSpaceGoesHere.YellowFrame">
      <Frame BackgroundColor="Yellow">
                <FlexLayout Direction="Column">
                    <Label Text="Panel 1"/>
                    <Label Text="A Panel"/>
                    <Button Text="Click Me"/>
                </FlexLayout>
      </Frame>
</StackLayout>

Dans le code derrière:

YellowFrame.xaml.cs:

public partial class YellowFrame : StackLayout {
   public YellowFrame() {
      InitializeComponent();
   }
}

Troisième étape

Maintenant, nous devons créer notre ViewModel que nous utiliserons pour notre ItemSource que nous appliquerons à FlexLayout, conformément à la documentation pour les mises en page pouvant être liées , toute mise en page qui "dérive de la mise en page" a la capacité d'avoir une mise en page pouvant être liée, FlexLayout en fait partie .

Faisons donc le ViewModel, je vais également créer un Enum pour le cadre Color que nous voulons rendre comme je l'ai montré dans l'instruction switch à la première étape, cependant, vous pouvez choisir ce que cela signifie pour décider comment dire quel modèle charger; ce n'est qu'un exemple possible.

BaseViewModel.cs:

public abstract class BaseViewModel : INotifyPropertyChanged {

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = ""){
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public virtual void CleanUp(){
        }
    }

ParentViewModel.cs:

public class ParentViewModel: BaseViewModel {
   private ObservableCollection<YourViewModel> myViewModels {get; set;}
   public ObservableCollection<YourViewModel> MyViewModels {
      get { return myViewModels;}
      set { 
          myViewModels = value;
          OnPropertyChanged("MyViewModels");
      }
   }

   public ParentViewModel() {
     LoadData();
   }

   private void LoadData() {
       //Let us populate our data here. 
       myViewModels = new ObservableCollection<YourViewModel>();

       myViewModels.Add(new YourViewModel {FrameColor = FrameColorEnum .Yellow});
       myViewModels.Add(new YourViewModel {FrameColor = FrameColorEnum .OrangeRed});
       myViewModels.Add(new YourViewModel {FrameColor = FrameColorEnum .ForestGreen});
      MyViewModels = myViewModels;
   }
}

YourViewModel.cs:

public class YourViewModel : BaseViewModel {
    public FrameColorEnum FrameColor {get; set;}
}

FrameColorEnum.cs:

public enum FrameColorEnum {
   Yellow,
   OrangeRed,
   ForestGreen
}

Nous y sommes presque, donc ce que nous avons fait jusqu'à présent, c'est que nous avons défini nos modèles de vue que nous utiliserons sur cette page, la dernière étape consiste à mettre à jour notre XAML global où nous appellerons notre sélecteur de modèle. Je ne mettrai à jour que les extraits nécessaires.

<ContentPage 
...
    **xmlns:views="your namespace where it was defined here, 
    normally you can just type the name of the Selector then have VS add the proper
    namespace and everything"**
<ContentPage.Resources>
<!--New stuff below-->
   <ResourceDictionary>
       <views:FrameTemplateSelector x:Key="FrameTemplateSelector"/>
   </ResourceDictionary>
</ContentPage.Resources>

<ScrollView Orientation="Both">
        <FlexLayout BindableLayout.ItemsSource="{Binding MyViewModels, Mode=TwoWay}"
                    BindableLayout.ItemTemplateSelector ="{StaticResource FrameTemplateSelector}"/>
    </ScrollView>

Image en direct: