Xamarin Forms, Dynamic ScrollView w XAML
Chcę utworzyć GUI, który ma podobny do tego, co generuje poniższy kod, przewijanie ramek.
Jednak chcę mieć możliwość przewijania ramek zawartości dynamicznej, najlepiej w języku XAML i wypełnionych źródłem elementu. Myślę, że nie jest to możliwe bez tworzenia niestandardowego widoku na podstawie widoku elementów z tego, co widzę. ListView i CollectionView nie robią tego, co chcę.
Myślę, że muszę użyć podglądu CarouselView, zastanawiałem się, czy jest sposób na zrobienie tego, czego szukam, bez.
<?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>
Dzięki Andy.
Odpowiedzi
Czy chcesz zaimplementować przewijalny widok, a każde dziecko zawiera wiele treści, które można przewijać w poziomie?
W przypadku tej funkcji spróbuj wyświetlić CarouselViewplik w formacie ListView.
Sprawdź kod:
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<CarouselView>
<CarouselView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Samouczek dotyczący CarouselView:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/carouselview/introduction
Przedmowa: Mam nadzieję, że dobrze zrozumiałem Twoją prośbę :)
Jeśli przez zawartość dynamiczną masz na myśli posiadanie dynamicznego szablonu elementu, możesz spróbować wykonać następujące czynności:
Krok pierwszy:
Zdefiniuj ItemTemplateSelector, możesz nadać mu nazwę, którą chcesz. W tej klasie zdefiniujemy, jakie mamy szablony, powiedzmy, że mamy trzy zdefiniowane przez Ciebie: 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;
}
}
Krok drugi:
Teraz, gdy zdefiniowaliśmy nasz selektor szablonów, przejdźmy dalej i zdefiniujmy nasze szablony, w tym przypadku odpowiednio nasze ramki Yellow, OrangeRed i ForestGreen. Po prostu pokażę, jak wykonać jedną z nich, ponieważ inne będą przestrzegać tego samego paradygmatu, wyłączając, oczywiście ze zmianą koloru. Zróbmy YellowFrame
W XAML będziesz mieć:
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>
W kodzie za:
YellowFrame.xaml.cs:
public partial class YellowFrame : StackLayout {
public YellowFrame() {
InitializeComponent();
}
}
Krok trzeci
Teraz musimy stworzyć nasz ViewModel, którego użyjemy dla naszego ItemSource, który zastosujemy do FlexLayout, zgodnie z dokumentacją dla Bindable Layouts , każdy układ, który "dervies from Layout" ma możliwość posiadania Bindable Layout, FlexLayout jest jednym z nich .
Zróbmy więc ViewModel, utworzę również Enum dla ramki Color, którą chcemy renderować, jak pokazałem w instrukcji switch w kroku pierwszym, jednak możesz wybrać, co kiedykolwiek oznacza decydowanie, jak określić, który szablon do załadowania; to tylko jeden możliwy przykład.
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
}
Jesteśmy prawie na miejscu, więc do tej pory zdefiniowaliśmy nasze modele widoku, których będziemy używać na tej stronie, a ostatnim krokiem jest aktualizacja naszego ogólnego kodu XAML, w którym nazwiemy nasz Selektor szablonów. Zaktualizuję tylko potrzebne fragmenty.
<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>
Obraz na żywo: