Xamarin Forms, Dynamic ScrollView в XAML
Я хочу создать графический интерфейс, похожий на то, что генерирует следующий код, - прокрутку кадров.
Однако я хочу иметь возможность прокрутки фреймов динамического содержимого, в идеале в 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>
Спасибо, Энди.
Ответы
Вы хотите реализовать прокручиваемое представление, и каждый дочерний элемент содержит несколько материалов, которые можно прокручивать по горизонтали?
Для этой функции попробуйте отобразить 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
Предисловие: Надеюсь, я правильно понял вашу просьбу :)
Если под динамическим контентом вы имеете в виду наличие динамического 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;
}
}
Шаг второй:
Теперь, когда мы определили наш Селектор шаблонов, давайте продолжим и определим наши шаблоны, в данном случае наши рамки 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();
}
}
Шаг третий
Теперь нам нужно создать нашу ViewModel, которую мы будем использовать для нашего ItemSource, который мы будем применять к FlexLayout, согласно документации для Bindable Layouts , любой макет, который "dervies from Layout" имеет возможность иметь Bindable Layout, FlexLayout является одним из них. .
Итак, давайте создадим ViewModel, я также создам Enum для фрейма Color, который мы хотим визуализировать, как я показал в операторе 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>
Живое изображение: