You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中如何组合ListView的DataTemplate实现可复用组件?

可复用ListView组件滚动卡顿优化方案

问题说明

需实现一款自带固定静态内容、允许用户自定义部分区域的可复用ListView组件。现有实现通过在DataTemplate中嵌套BindableLayout+转换器的方式加载自定义模板,但滚动时出现明显卡顿现象。

原实现卡顿原因

  1. 转换器DataTemplateItemSourceConverter每次绑定都会创建新的ObservableCollection对象,ListView滚动复用Item时频繁触发对象创建,引发GC压力
  2. 嵌套的BindableLayout增加了UI布局层级,提升了渲染复杂度

优化方案

移除BindableLayout与转换器,改用ContentPresenter直接加载自定义模板,简化布局结构并减少不必要的对象创建。

优化后的自定义ListView XAML

<ListView
    x:Class="ReusableListView.CustomListView"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Name="this">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid ColumnDefinitions="Auto, Auto, *" RowDefinitions="*, *">
                    <!-- 内置静态内容:复选框 -->
                    <CheckBox 
                        Grid.RowSpan="2"
                        Grid.Column="0"
                        HorizontalOptions="Center" 
                        VerticalOptions="Center" />
                    <!-- 内置静态内容:分隔线 -->
                    <BoxView
                        Grid.RowSpan="2"
                        Grid.Column="1"
                        BackgroundColor="LightGray"
                        WidthRequest="1" />
                    <!-- 用户自定义内容区域 -->
                    <ContentPresenter
                        Grid.RowSpan="2"
                        Grid.Column="2"
                        Content="{Binding}"
                        ContentTemplate="{Binding PartialTemplate, Source={x:Reference this}}"
                        VerticalOptions="Center"
                        Padding="4,0,0,0" />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

自定义ListView代码后置(无需修改)

public partial class CustomListView : ListView
{
    public CustomListView()
    {
        InitializeComponent();
    }

    static CustomListView()
    {
        PartialTemplateProperty = BindableProperty.Create(nameof(PartialTemplate), typeof(DataTemplate), typeof(CustomListView));
    }

    public static readonly BindableProperty PartialTemplateProperty;

    public DataTemplate PartialTemplate
    {
        get => (DataTemplate)base.GetValue(PartialTemplateProperty);
        set => base.SetValue(PartialTemplateProperty, value);
    }
}

移除冗余文件

删除DataTemplateItemSourceConverter类,该转换器已不再需要。

主页面使用方式(保持不变)

XAML:

<ContentPage
    x:Class="ReusableListView.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:lv="clr-namespace:ReusableListView">
    <lv:CustomListView ItemsSource="{Binding Data}">
        <lv:CustomListView.PartialTemplate>
            <DataTemplate>
                <Label VerticalOptions="Center">
                    <Label.Text>
                        <MultiBinding StringFormat="{}Item Id: {0}">
                            <Binding Path="Id" />
                        </MultiBinding>
                    </Label.Text>
                </Label>
            </DataTemplate>
        </lv:CustomListView.PartialTemplate>
    </lv:CustomListView>
</ContentPage>

代码后置:

public partial class MainPage : ContentPage
{
    public ObservableCollection<Data> Data { get; set; }
    public MainPage()
    {
        InitializeComponent();
        BindingContext = this;
        Data = new(Enumerable.Range(0, 100).Select(x => new Data() { Id = Guid.NewGuid() }));
        OnPropertyChanged(nameof(Data));
    }
}

public class Data
{
    public Guid Id { get; set; }
}

优化效果

  • 消除了频繁创建ObservableCollection带来的GC压力
  • 简化布局层级,降低UI渲染负载
  • ListView滚动流畅度明显提升,无卡顿现象

内容的提问来源于stack exchange,提问作者rsnate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:23:21