Xamarin Forms, XAML의 동적 ScrollView

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을 갖는 것을 의미하는 경우 다음을 시도 할 수 있습니다.

1 단계 :

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

2 단계 :

이제 템플릿 선택기를 정의 했으므로 템플릿을 정의하겠습니다.이 경우에는 각각 Yellow, 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();
   }
}

3 단계

이제 Bindable Layouts에 대한 문서에 따라 FlexLayout에 적용 할 ItemSource에 사용할 ViewModel을 만들어야 합니다. "Layout에서 파생 된"레이아웃은 Bindable 레이아웃을 가질 수 있고 FlexLayout이 그중 하나입니다. .

이제 ViewModel을 만들어 보겠습니다. 1 단계의 switch 문에서 보여준 것처럼 렌더링하려는 Color 프레임에 대한 Enum도 만들겠습니다. 그러나로드 할 템플릿을 지정하는 방법을 결정하는 방법을 선택할 수 있습니다. 이것은 하나의 가능한 예일뿐입니다.

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>

라이브 사진 :