MAUI 的
DataTemplateSelector就是用来让同一个列表(比如
CollectionView或
ListView)根据数据内容自动切换不同 UI 模板的工具。它不靠写一堆
if-else在 XAML 里判断,而是把“选哪个模板”这件事抽成一个可复用、可测试的类。
定义继承自 DataTemplateSelector 的选择器类
新建一个 C# 类,继承
DataTemplateSelector,重写
OnSelectTemplate方法。这个方法接收当前数据项(
object item)和容器(
BindableObject container),返回你决定用的模板。 确保你的数据模型有区分逻辑的字段或类型,比如
MessageType、
IsSystem、
ItemType等 在类中声明多个
DataTemplate属性,对应不同 UI 样式
OnSelectTemplate里做类型判断或属性判断,别忘了加空值防护
示例:
public class MessageTemplateSelector : DataTemplateSelector
{
public DataTemplate UserTemplate { get; set; }
public DataTemplate SystemTemplate { get; set; }
<pre class="brush:php;toolbar:false;">protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return item switch
{
UserMessage _ => UserTemplate,
SystemMessage _ => SystemTemplate,
_ => UserTemplate
};
}}
在 XAML 中声明模板和选择器
在页面或应用资源中定义
DataTemplate,并把它们赋给选择器的属性。注意:模板要放在选择器内部,且必须用属性名匹配(如
UserTemplate)。 模板定义写在
<messagetemplateselector></messagetemplateselector>标签内,不是外面 每个
DataTemplate内部可以自由写布局,支持绑定、命令、事件等 确保命名空间已正确引入:
xmlns:local="clr-namespace:YourApp.Namespace"
示例(XAML 片段):
<ContentPage.Resources>
<local:MessageTemplateSelector x:Key="MsgSelector">
<local:MessageTemplateSelector.UserTemplate>
<DataTemplate>
<StackLayout Padding="10" BackgroundColor="LightBlue">
<Label Text="{Binding Text}" TextColor="Black"/>
</StackLayout>
</DataTemplate>
</local:MessageTemplateSelector.UserTemplate>
<local:MessageTemplateSelector.SystemTemplate>
<DataTemplate>
<StackLayout Padding="10" BackgroundColor="Gray">
<Label Text="{Binding Text}" TextColor="White" FontAttributes="Bold"/>
</StackLayout>
</DataTemplate>
</local:MessageTemplateSelector.SystemTemplate>
</local:MessageTemplateSelector>
</ContentPage.Resources>在 CollectionView 中绑定使用
把
ItemsSource绑定到数据集合后,直接设置
ItemTemplate为刚才定义的选择器资源即可。框架会在渲染每一项时自动调用
OnSelectTemplate。 只支持
CollectionView和
CarouselView(
ListView在 MAUI 中已不推荐用于新项目) 确保集合里的对象是具体类型(不是
object),否则
is判断会失效 如果模板里用了绑定,记得数据模型实现
INotifyPropertyChanged,否则更新不生效
示例:
<CollectionView ItemsSource="{Binding Messages}"
ItemTemplate="{StaticResource MsgSelector}" />基本上就这些。关键不在写多少代码,而在于把“长什么样”和“什么时候用”这两件事干净地分开——模板管样式,选择器管逻辑,数据管内容。
