Xamarin Forms, XAML'de Dinamik ScrollView

Sep 12 2020

Aşağıdaki kodun oluşturduğuna benzer bir çerçeve kaydırması olan bir GUI oluşturmak istiyorum.

Bununla birlikte, ideal olarak XAML'de ve bir Öğe kaynağıyla doldurulmuş dinamik içerik çerçevelerinin bir kaydırmasına sahip olmak istiyorum. Gördüğüm şeyden öğe görünümüne dayalı özel bir görünüm oluşturmadan bunun mümkün olduğunu sanmıyorum. ListView ve CollectionView tam olarak istediğimi yapmıyor.

CarouselView önizlemesini kullanmam gerektiğini düşünüyorum, peşinde olduğum şeyi yapmanın bir yolu olup olmadığını merak ediyordum.

<?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>

Teşekkürler Andy.

Yanıtlar

1 JarvanZhang-MSFT Sep 14 2020 at 15:26

Kaydırılabilir bir görünüm uygulamak istiyor musunuz ve her çocuk yatay olarak kaydırılabilen birden çok içerik barındırıyor?

Bu özellik için CarouselView, bir ListView.

Kodu kontrol edin:

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

CarouselView hakkında eğitim:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/carouselview/introduction

1 SomeStudent Sep 12 2020 at 10:12

Önsöz: Umarım isteğinizi doğru anlamışımdır :)

Dinamik içerikle dinamik bir ItemTemplate olmasını kastediyorsanız, şunları yapmayı deneyebilirsiniz:

Adım bir:

Bir ItemTemplateSelector tanımlayın, istediğiniz ismi verebilirsiniz. Bu sınıfta ne tür şablonlara sahip olduğumuzu tanımlayacağız, diyelim ki sizin tanımladığınız üç tanesine sahibiz: Sarı, TuruncuKırmızı, Orman Yeşili

   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;
       }
   }

İkinci adım:

Şablon Seçicimizi tanımladığımıza göre, devam edip şablonlarımızı tanımlayalım, bu durumda sırasıyla Sarı, TuruncuKırmızı ve ForestGreen çerçevelerimizi. Sadece bir tanesini nasıl yapacağımı göstereceğim çünkü diğerleri aynı paradigmayı takip edecekler, tabii ki renk değişiyor. YellowFrame'i yapalım

XAML'de şunlara sahip olacaksınız:

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>

Arkasındaki kodda:

YellowFrame.xaml.cs:

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

Adım üç

Şimdi, Bağlanabilir Mizanpaj belgelerine göre FlexLayout'a uygulayacağımız ItemSource için kullanacağımız ViewModel'imizi oluşturmamız gerekiyor , "Layout'tan gelen herhangi bir mizanpaj Bağlanabilir Düzene sahip olabilir, FlexLayout bunlardan biridir. .

Öyleyse ViewModel'i yapalım, birinci adımdaki switch deyiminde gösterdiğim gibi render etmek istediğimiz Renk çerçevesi için de bir Enum oluşturacağım, ancak hangi şablonun yükleneceğini nasıl söyleyeceğinize karar vermenin ne anlama geldiğini seçebilirsiniz; bu sadece olası bir örnektir.

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
}

Neredeyse oradayız, bu yüzden şimdiye kadar yaptığımız şey, o sayfada kullanacağımız görünüm modellerimizi tanımladık, son adım, Şablon Seçicimiz olarak adlandıracağımız genel XAML'imizi güncellemektir. Yalnızca gereken parçacıkları güncelleyeceğim.

<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>

Canlı Görüntü: