Xamarin Forms, Dynamic ScrollView ใน XAML

Sep 12 2020

ฉันต้องการสร้าง GUI ที่คล้ายกับสิ่งที่สร้างโค้ดต่อไปนี้คือการเลื่อนเฟรม

อย่างไรก็ตามฉันต้องการให้มีการเลื่อนของเฟรมเนื้อหาแบบไดนามิกตามหลักการแล้วใน XAML และเติมข้อมูลด้วยแหล่งที่มาของรายการ ฉันไม่คิดว่าสิ่งนี้จะเป็นไปได้หากไม่สร้างมุมมองที่กำหนดเองตามมุมมองรายการจากสิ่งที่ฉันเห็น ListView และ CollectionView ไม่ค่อยทำในสิ่งที่ฉันต้องการ

ฉันคิดว่าฉันต้องใช้ CarouselView ดูตัวอย่างฉันสงสัยว่ามีวิธีทำในสิ่งที่ฉันไม่ต้องการหรือไม่

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

ขอบคุณแอนดี้

คำตอบ

1 JarvanZhang-MSFT Sep 14 2020 at 15:26

คุณต้องการใช้มุมมองที่เลื่อนได้หรือไม่และเด็กแต่ละคนมีเนื้อหาหลายรายการที่สามารถเลื่อนได้ในแนวนอน?

สำหรับคุณสมบัตินี้ให้ลองแสดงCarouselViewในไฟล์ListView.

ตรวจสอบรหัส:

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

บทช่วยสอนเกี่ยวกับ CarouselView:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/carouselview/introduction

1 SomeStudent Sep 12 2020 at 10:12

คำนำ: ฉันหวังว่าฉันจะเข้าใจคำขอของคุณอย่างถูกต้อง :)

หากตามเนื้อหาแบบไดนามิกคุณหมายถึงการมี ItemTemplate แบบไดนามิกคุณสามารถลองทำสิ่งต่อไปนี้:

ขั้นตอนแรก:

กำหนด ItemTemplateSelector คุณสามารถตั้งชื่อที่คุณต้องการได้ ในคลาสนี้เราจะกำหนดประเภทของเทมเพลตที่เรามีสมมติว่าเรามีสามแบบที่คุณกำหนดไว้: Yellow, 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;
       }
   }

ขั้นตอนที่สอง:

ตอนนี้เราได้กำหนด Template Selector ของเราแล้วให้เราดำเนินการต่อและกำหนดเทมเพลตของเราในกรณีนี้เฟรมสีเหลือง OrangeRed และ ForestGreen ของเราตามลำดับ ฉันจะแสดงวิธีสร้างหนึ่งในนั้นเนื่องจากคนอื่น ๆ จะทำตามกระบวนทัศน์เดียวกันยกเว้นโดยแน่นอนว่าสีจะเปลี่ยนไป มาทำ YellowFrame กัน

ใน XAML คุณจะมี:

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>

ในโค้ดด้านหลัง:

YellowFrame.xaml.cs:

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

ขั้นตอนที่สาม

ตอนนี้เราจำเป็นต้องสร้าง ViewModel ของเราที่เราจะใช้สำหรับ ItemSource ของเราที่เราจะนำไปใช้กับ FlexLayout ตามเอกสารสำหรับBindable Layoutsเลย์เอาต์ใด ๆ ที่ "dervies from Layout" มีความสามารถในการมีเค้าโครงที่ผูกมัดได้ FlexLayout ก็เป็นหนึ่งในนั้น .

ดังนั้นให้เราสร้าง ViewModel ฉันจะสร้าง Enum สำหรับกรอบสีที่เราต้องการแสดงผลตามที่ฉันแสดงในคำสั่ง switch ในขั้นตอนที่หนึ่งอย่างไรก็ตามคุณสามารถเลือกวิธีการตัดสินใจได้ว่าจะบอกเทมเพลตใดที่จะโหลดได้อย่างไร นี่เป็นเพียงตัวอย่างหนึ่งที่เป็นไปได้

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
}

เราเกือบจะถึงจุดนั้นแล้วสิ่งที่เราได้ทำไปแล้วคือการกำหนดโมเดลมุมมองของเราที่เราจะใช้ในหน้านั้นขั้นตอนสุดท้ายคือการอัปเดต XAML โดยรวมของเราซึ่งเราจะเรียกตัวเลือกเทมเพลตของเรา ฉันจะอัปเดตเฉพาะส่วนย่อยที่จำเป็นเท่านั้น

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

ภาพสด: