问题描述
我正在尝试为我的 Xamarin.Forms 项目中的表单制作模板。
我想使用 SyncFusion SfCarousel
控件,并且由于我在许多表单上重用它,我想制作一个 xaml 视图,我可以在目标表单上实例化该视图,而不必每次都重新创建控件.
这是问题所在,我有 TapGestureRecognizer.OnTapped
和其他几个传递给此控件的 Data 对象。
以下是此次实施的示例。
....
<DataTemplate x:Key="CarouselitemTemplate">
<StackLayout Orientation="Vertical">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
CommandParameter="{Binding Path=.}"
NumberOfTapsrequired="1"
Tapped="OnTapped" />
</StackLayout.GestureRecognizers>
<Image
Aspect="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}" />
....
我想做的是这个。 TemplateCarouselView.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<syncfusion:SfCarousel
x: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>
<TapGestureRecognizer
CommandParameter="{Binding Path=.}"
NumberOfTapsrequired="1"
Tapped="{Binding Path=OnTapped}" />
</StackLayout.GestureRecognizers>
<Image
Aspect="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);
}
}
}
}
我想我可以使用 BindableProperty
来允许调用实例将它自己的指针添加到 Tap Callback 函数。
然后我可以像这样实现这个视图。
<myviews:TemplateCarouselView OnTapped="SomeFunction" />
我的问题是这样的。
- 此实现能否继承模板中的
viewmodel
?或者我是否需要为每个BindableProperty
创建Value="{Binding Path=xxx}"
元素。 -
OnTapped
的实现没有移交给TapGestureRecognizer
我不知道如何重载传入的属性以供 xaml 实现接受。 - 实现此 View 的每个实例都需要有自己的重载
OnTapped
函数,因此我不能只在 TemplateView 中进行内部调用。 - 我能否让这个模板使用它自己的内部
viewmodel
,同时仍然能够继承父表单viewmodel
?
感谢您的任何想法或指点!
干杯! 杰西
解决方法
我终于搞定了! 这是我的工作方式,如果有人有更好的方法或方法来实现这一点,我很乐意听到它!
这是我必须制作的模板类
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);
}
}
}
}
然后我可以像这样实例化它
<core:TemplateCarouselView
x:Name="carousel"
ActionList="{Binding Path=ActionList}"
KeyButton="{x:Reference KeyImageButton}"
ParentObject="{Binding Path=MyClass}" />
这需要一些时间,没有一些帮助我无法完成!
干杯!