Hello everyone,
I am trying to make a template for a form on my Xamarin.Forms project.
I
want to use a SyncFusion Carousel control, and since I reuse it on a
number of forms, I would like to make a xaml view that I can just
instantiate on the target form saving from having to recreate the
control every time.
Here is the problem, I have TapGestureRecognizers and several other Data objects that get passed to this control.
Here are the samples of how it gets implemented as this time.
<DataTemplate x:Key="CarouselitemTemplate"><StackLayout Orientation="Vertical"><StackLayout.GestureRecognizers><TapGestureRecognizerCommandParameter="{Binding Path=.}"NumberOfTapsRequired="1"Tapped="OnTapped" /></StackLayout.GestureRecognizers><ImageAspect="AspectFit"HeightRequest="350"Source="{Binding Path=Image, Converter={StaticResource Key=FillImageFromBytes}}"WidthRequest="325" /><Label HorizontalTextAlignment="Center" Text="{Binding Path=FileName}" /></StackLayout></DataTemplate>....<Label Text="Images" /><syncfusion:SfCarousel x:Name="carousel" ItemTemplate="{StaticResource Key=CarouselitemTemplate}" />....
What I would like to do is this.
TemplateCarouselView.xaml
<?xml version="1.0" encoding="UTF-8" ?><syncfusion:SfCarouselx:Class="BoomStick.Views.TemplateCarouselView"xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:syncfusion="clr-namespace:Syncfusion.SfCarousel.XForms;assembly=Syncfusion.SfCarousel.XForms"><syncfusion:SfCarousel.ItemTemplate><DataTemplate><StackLayout Orientation="Vertical"><StackLayout.GestureRecognizers><TapGestureRecognizerCommandParameter="{Binding Path=.}"NumberOfTapsRequired="1"Tapped="{Binding Path=OnTapped}" /></StackLayout.GestureRecognizers><ImageAspect="AspectFit"HeightRequest="350"Source="{Binding Path=Image, Converter={StaticResource Key=FillImageFromBytes}}"WidthRequest="325" /><Label HorizontalTextAlignment="Center" Text="{Binding Path=FileName}" /></StackLayout></DataTemplate></syncfusion:SfCarousel.ItemTemplate></syncfusion:SfCarousel
TemplateCarouselView.xaml.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Syncfusion.SfCarousel.XForms;using Xamarin.Forms;using Xamarin.Forms.Xaml;namespace BoomStick.Views{[XamlCompilation(XamlCompilationOptions.Compile)]public partial class TemplateCarouselView : SfCarousel{public TemplateCarouselView(){InitializeComponent();}public static readonly BindableProperty OnTappedProperty = BindableProperty.Create(nameof(OnTapped), typeof(Command), typeof(Command));public Command OnTapped{get{return (Command)GetValue(OnTappedProperty);}set{SetValue(OnTappedProperty, value);}}}}
I figured I could use the BindableProperty to allow the calling instance to add it's own pointer to the Tap Callback function.
I could then implement this view like so.
<myviews:TemplateCarouselView OnTapped="SomeFunction" />
The problems I have are thus.
Can this implementation inherit the ViewModel within the template? or do I need to create BindableProperty elements for each then {Binding Path=xxx}
The implementation for the OnTapped is not handing off to the TapGestureRecognizer I cannot figure out how to overload the incoming property to be accepted by the xaml implementation.
Each instance that implements this View needs to have it's own overloaded OnTapped function, so I cannot just make it an internal call within the TemplateView.
Can I make this template use it's own internal ViewModel while still being able to inherit the parent forms ViewModel?
Thank you for any ideas or pointers!
Cheers!
Jesse
Hello everyone,
I am trying to make a template for a form on my Xamarin.Forms project.
I want to use a SyncFusion Carousel control, and since I reuse it on a number of forms, I would like to make a xaml view that I can just instantiate on the target form saving from having to recreate the control every time.Here is the problem, I have
TapGestureRecognizersand several other Data objects that get passed to this control.
Here are the samples of how it gets implemented as this time.
<DataTemplate x:Key="CarouselitemTemplate"><StackLayout Orientation="Vertical"><StackLayout.GestureRecognizers><TapGestureRecognizerCommandParameter="{Binding Path=.}"NumberOfTapsRequired="1"Tapped="OnTapped" /></StackLayout.GestureRecognizers><ImageAspect="AspectFit"HeightRequest="350"Source="{Binding Path=Image, Converter={StaticResource Key=FillImageFromBytes}}"WidthRequest="325" /><Label HorizontalTextAlignment="Center" Text="{Binding Path=FileName}" /></StackLayout></DataTemplate>....<Label Text="Images" /><syncfusion:SfCarousel x:Name="carousel" ItemTemplate="{StaticResource Key=CarouselitemTemplate}" />....What I would like to do is this.
TemplateCarouselView.xaml
<?xml version="1.0" encoding="UTF-8" ?><syncfusion:SfCarouselx:Class="BoomStick.Views.TemplateCarouselView"xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:syncfusion="clr-namespace:Syncfusion.SfCarousel.XForms;assembly=Syncfusion.SfCarousel.XForms"><syncfusion:SfCarousel.ItemTemplate><DataTemplate><StackLayout Orientation="Vertical"><StackLayout.GestureRecognizers><TapGestureRecognizerCommandParameter="{Binding Path=.}"NumberOfTapsRequired="1"Tapped="{Binding Path=OnTapped}" /></StackLayout.GestureRecognizers><ImageAspect="AspectFit"HeightRequest="350"Source="{Binding Path=Image, Converter={StaticResource Key=FillImageFromBytes}}"WidthRequest="325" /><Label HorizontalTextAlignment="Center" Text="{Binding Path=FileName}" /></StackLayout></DataTemplate></syncfusion:SfCarousel.ItemTemplate></syncfusion:SfCarouselTemplateCarouselView.xaml.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Syncfusion.SfCarousel.XForms;using Xamarin.Forms;using Xamarin.Forms.Xaml;namespace BoomStick.Views{[XamlCompilation(XamlCompilationOptions.Compile)]public partial class TemplateCarouselView : SfCarousel{public TemplateCarouselView(){InitializeComponent();}public static readonly BindableProperty OnTappedProperty = BindableProperty.Create(nameof(OnTapped), typeof(Command), typeof(Command));public Command OnTapped{get{return (Command)GetValue(OnTappedProperty);}set{SetValue(OnTappedProperty, value);}}}}I figured I could use the
BindablePropertyto allow the calling instance to add it's own pointer to the Tap Callback function.
I could then implement this view like so.
<myviews:TemplateCarouselView OnTapped="SomeFunction" />The problems I have are thus.
Can this implementation inherit the ViewModel within the template? or do I need to create
BindablePropertyelements for each then{Binding Path=xxx}The implementation for the
OnTappedis not handing off to theTapGestureRecognizerI cannot figure out how to overload the incoming property to be accepted by the xaml implementation.Each instance that implements this
Viewneeds to have it's own overloadedOnTappedfunction, so I cannot just make it an internal call within the TemplateView.Can I make this template use it's own internal ViewModel while still being able to inherit the parent forms ViewModel?
- Can I use this type of a template to make a `CardView`, defining custom cards in this manner then creating an `ObservableCollection<MyControl>()`
Thank you for any ideas or pointers!
Cheers!
Jesse
Here is the template class I had to make
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoomStick.Models;
using BoomStick.Services;
using Syncfusion.SfCarousel.XForms;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace BoomStick.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TemplateCarouselView : SfCarousel
{
public DataTemplate dt;
public TemplateCarouselView()
{
InitializeComponent();
dt = new DataTemplate(() =>
{
var keyLayout = new StackLayout();
var bindPhoto = new Binding()
{
Converter = new FillImageFromBytes(),
Path = "Image"
};
var bindTapped = new Binding()
{
Path = "OnTapped"
};
var bindLocalPath = new Binding()
{
Converter = new FillImageFromBytes(),
Path = "."
};
var tgRec = new TapGestureRecognizer()
{
CommandParameter = bindLocalPath,
NumberOfTapsRequired = 1
};
tgRec.Tapped += async (s, e) =>
{
var act = await Application.Current.MainPage.DisplayActionSheet(
StringTools.GetStringResource("szPhotoOptions"),
null,
StringTools.GetStringResource("szOK"),
ActionList.ToArray());
await TapHandler.ImageTapHandler((Photos)((TappedEventArgs)e).Parameter, act, KeyButton, ParentObject);
};
tgRec.SetBinding(TapGestureRecognizer.CommandProperty, bindTapped);
tgRec.SetBinding(TapGestureRecognizer.CommandParameterProperty, ".");
keyLayout.GestureRecognizers.Add(tgRec);
var img = new Image()
{
Aspect = Aspect.AspectFit,
HeightRequest = 350,
WidthRequest = 250,
};
img.SetBinding(Image.SourceProperty, bindPhoto);
var lblFileName = new Label()
{
HorizontalTextAlignment = TextAlignment.Center,
};
lblFileName.SetBinding(Label.TextProperty, "FileName");
keyLayout.Children.Add(img);
keyLayout.Children.Add(lblFileName);
return new ViewCell { View = keyLayout };
});
Carousel.ItemTemplate = dt;
}
public static readonly BindableProperty ActionListProperty = BindableProperty.Create(nameof(ActionList), typeof(List<string>), typeof(List<string>));
public List<string> ActionList
{
get
{
return (List<string>)GetValue(ParentObjectProperty);
}
set
{
SetValue(ParentObjectProperty, value);
}
}
public static readonly BindableProperty ParentObjectProperty = BindableProperty.Create(nameof(ParentObject), typeof(Object), typeof(Object));
public Object ParentObject
{
get
{
return (Object)GetValue(ParentObjectProperty);
}
set
{
SetValue(ParentObjectProperty, value);
}
}
public static readonly BindableProperty KeyButtonProperty = BindableProperty.Create(nameof(KeyButton), typeof(ImageButton), typeof(ImageButton));
public ImageButton KeyButton
{
get
{
return (ImageButton)GetValue(KeyButtonProperty);
}
set
{
SetValue(KeyButtonProperty, value);
}
}
}
}
I can then instantiate it like this
<core:TemplateCarouselView
x:Name="carousel"
ActionList="{Binding Path=ActionList}"
KeyButton="{x:Reference KeyImageButton}"
ParentObject="{Binding Path=MyClass}" />
It took some time, and I couldn't have done it without some help!
Cheers!