xamarin表单类DataTemplate
在ctor中使用Type
接收参数。
public class DataTemplate : ElementTemplate, IDataTemplateController
{
public DataTemplate(Type type);
...
}
如何在XAML中将特定类的类型传递给ctor?在c#中,我将编写new DataTemplate(typeof(DeviceViewModel))
。但是我必须用XAML编写。
伪代码:
<DataTemplate>
<x:Arguments>
<typeof(viewModels:DeviceViewModel)/>
</x:Arguments>
<myControls:MyCustomControl/>
</DataTemplate>
编辑
为使目标更加明确,我创建了一个派生示例。假设有以下结构:
我的列表包含这些元素。每种类型都必须在自己的DataTemplate
中进行处理。在我的情况下,项目非常复杂,所以这就是为什么我为每个项目创建一个ViewModel的原因。在代码中,它可能看起来像这样:
public abstract class BaseViewModel
public class PictureViewModel : BaseViewModel
public class MusicViewModel : BaseViewModel
public class DocumentViewModel : BaseViewModel
/* My List full of different ViewModels*/
List<BaseViewModel> itemList;
现在,我创建一个包含其他TemplateSelector
的{{1}}。它根据视图模型类型调用正确的一个:
TemplateSelector
在XAML中,所有分配均发生:
using System;
using Xamarin.Forms;
using MyApp.ViewModels;
namespace MyApp.TemplateSelectors
{
public class MyItemTemplateSelector : DataTemplateSelector
{
public DataTemplateSelector PictureTemplateSelector { get; set; }
public DataTemplateSelector MusicTemplateSelector { get; set; }
public DataTemplateSelector DocumentTemplateSelector { get; set; }
public DataTemplateSelector DefaultTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
switch (item)
{
case PictureViewModel vm:
return PictureTemplateSelector.SelectTemplate(item, container);
case MusicViewModel vm:
return MusicTemplateSelector.SelectTemplate(item, container);
case DocumentViewModel vm:
return DocumentTemplateSelector.SelectTemplate(item, container);
default:
return DefaultTemplate.SelectTemplate(item, container);
}
}
}
}
最后绑定MyItems(类型为<DataTemplate x:Key="PictureDefaultTemplate">
<ViewCell>
<Image Source="{Binding FilePath}"/>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="MusicDefaultTemplate">
<ViewCell>
<Button Text="Play this!"/>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="DocumentDefaultTemplate">
<ViewCell>
<Label Text="show filename at least"/>
</ViewCell>
</DataTemplate>
<!-- The DocumentTemplateSelector handles file extensions differently -->
<DataTemplate x:Key="MyTxtTemplate">
<ViewCell>
<Label Text="This is a text file"/>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="MyPdfTemplate">
<ViewCell>
<Label Text="This is a pdf file"/>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="MyXmlTemplate">
<ViewCell>
<Label Text="This is a xml File"/>
</ViewCell>
</DataTemplate>
<!--provide specific template selectors with initiated datatemplates-->
<templateSelectors:PictureTemplateSelector x:Key="pictureTemplateSelector" DefaultTemplate="{StaticResource PictureDefaultTemplate}"/>
<templateSelectors:MusicTemplateSelector x:Key="musicTemplateSelector" DefaultTemplate="{StaticResource MusicDefaultTemplate}"/>
<templateSelectors:DocumentTemplateSelector x:Key="documentTemplateSelector" DefaultTemplate="{StaticResource DocumentDefaultTemplate}"
TxtTemplate="{StaticResource MyTxtTemplate}"
PdfTemplate="{StaticResource MyPdfTemplate}"
XmlTemplate="{StaticResource MyXmlTemplate}"/>
<!--provide superior template selector with other template selectors -->
<templateSelectors:MyItemTemplateSelector x:Key="myItemTemplateSelector"
PictureTemplateSelector="{StaticResource pictureTemplateSelector}"
MusicTemplateSelector="{StaticResource musicTemplateSelector}"
DocumentTemplateSelector="{StaticResource documentTemplateSelector}"/>
的对象)并设置上级模板选择器。这是我将BaseViewModel
设置为CachingStrategy
的地方:
RecycleElementAndDataTemplate
在DocumentTemplateSelector中引发异常。
<ListView ItemsSource="{Binding MyItems}"
ItemTemplate="{StaticResource myItemTemplateSelector}"
IsPullToRefreshEnabled="True"
CachingStrategy="RecycleElementAndDataTemplate"/>
引发以下异常:
System.NotSupportedException:RecycleElementAndDataTemplate要求使用ctor作为类型激活DataTemplate。
@IvanIčin@ G.hakim我不担心默认机制不起作用,但是在研究了来自github的xamarin表单代码后,我发现没有其他解决方案可以使它工作而不在using System;
using Xamarin.Forms;
using MyApp.ViewModels;
namespace MyApp.TemplateSelectors
{
public class DocumentTemplateSelector : DataTemplateSelector
{
public DataTemplate TxtTemplate { get; set; }
public DataTemplate PdfTemplate { get; set; }
public DataTemplate XmlTemplate { get; set; }
public DataTemplate DefaultTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
var doc = (DocumentViewModel)item;
switch (doc.FileExtension)
{
case "txt":
return TxtTemplate; // Exception
case "pdf":
return PdfTemplate; // Exception
case "xml":
return XmlTemplate; // Exception
default:
return DefaultTemplate; // Exception
}
}
}
}
ctor中传递类型