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

.NET MAUI ListView绑定不同子类数据出现绑定错误求助

问题:ListView结合DataTemplateSelector显示多类型项时出现绑定错误

我定义了三个类:

abstract public class PlanPosition
{
    public long Id { get; set; }
    public Plan? Plan { get; set; } = null;
    public int Pos { get; set; }
}

public class AddressPos:PlanPosition
{
    public Address Address { get; set; } 
    public LocomotionType LocomotionType { get; set; }
}

public class DayPos:PlanPosition
{
    public int Day {  get; set; }
}

我有一个包含AddressPos或DayPos类型元素的PlanPosition列表,使用带有DataTemplateSelector的ListView时出现大量绑定错误。XAML代码片段如下:

<ContentPage.Resources>
    <util:DateOnlyToDateTimeConverter x:Key="DateConverter"/>
    <DataTemplate x:Key="AddressPosTemplate"
                  x:DataType="data:AddressPos">
        <ViewCell>
            <Border HorizontalOptions="Start"
                    WidthRequest="300"
                    Padding="5"
                    Margin="20"
                    StrokeShape="RoundRectangle 10,10,10,10">

                <VerticalStackLayout>
                    <HorizontalStackLayout Spacing="5">
                        <HorizontalStackLayout.Triggers>
                            <DataTrigger TargetType="HorizontalStackLayout" Binding="{Binding Pos}" Value="1">
                                <Setter Property="IsVisible" Value="False"/>
                            </DataTrigger>
                        </HorizontalStackLayout.Triggers>
...
                    </HorizontalStackLayout>
                    <Label Text="{Binding Name}"
                           FontAttributes="Bold"
                           FontSize="12"/>
                </VerticalStackLayout>
            </Border>
        </ViewCell>
    </DataTemplate>

    <DataTemplate x:Key="DayPosTemplate"
                  x:DataType="data:DayPos">
        <ViewCell>
            <Border HorizontalOptions="Start"
                    WidthRequest="100"
                    BackgroundColor="LightGray"
                    Padding="5"
                    Margin="10"
                    StrokeShape="RoundRectangle 10,10,10,10">
                <HorizontalStackLayout HorizontalOptions="Center"
                                       Spacing="5">
                    <Image Source="menu_burger.png" HeightRequest="20" VerticalOptions="Center"/>
                    <Label Text="{Binding Day,StringFormat='Tag {0:D}'}" FontAttributes="Bold" VerticalOptions="Center"/>
                    <ImageButton x:Name="delButton" Source="trash.png" 
                                 HeightRequest="20" 
                                 IsVisible="False" 
                                 Padding="0"
                                 Margin="0"
                                 BackgroundColor="LightGray"/>
                </HorizontalStackLayout>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup Name="CommonStates">
                        <VisualState Name="Normal">
                            <VisualState.Setters>
                                <Setter TargetName="delButton" Property="ImageButton.IsVisible" Value="False"/>
                                <Setter Property="WidthRequest" Value="100"/>
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState Name="PointerOver">
                            <VisualState.Setters>
                                <Setter TargetName="delButton" Property="ImageButton.IsVisible" Value="True"/>
                                <Setter Property="WidthRequest" Value="150"/>
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </Border>
        </ViewCell>
    </DataTemplate>

    <util:PlanPosDataTemplateSelector x:Key="PosSelector"
                                      AddressPos="{StaticResource AddressPosTemplate}"
                                      DayPos="{StaticResource DayPosTemplate}"/>
</ContentPage.Resources>

ListView的数据源是List<PlanPosition>,不同DataTemplate的x:DataType分别指定为AddressPos或DayPos,但出现类似以下绑定错误:

Schweregrad Anzahl  Datenkontext    Bindungspfad    Ziel    Zieltyp Beschreibung    Datei   Zeile   Projekt
Fehler  24  PlannerViewModel    Pos HorizontalStackLayout.Bound Object  'Pos' property not found on 'TripPlanner.Planner.PlannerViewModel', target property: 'Microsoft.Maui.Controls.HorizontalStackLayout.Bound'  E:\NETProjects\Tripplanner\TripPlanner\Planner\PlannerPage.xaml 23  TripPlanner

Schweregrad Anzahl  Datenkontext    Bindungspfad    Ziel    Zieltyp Beschreibung    Datei   Zeile   Projekt
Fehler  14  PlannerViewModel    Day Label.Text  String  'Day' property not found on 'TripPlanner.Planner.PlannerViewModel', target property: 'Microsoft.Maui.Controls.Label.Text'   E:\NETProjects\Tripplanner\TripPlanner\Planner\PlannerPage.xaml 52  TripPlanner

我想知道是不是无法在ListView中显示不同类的项?目前想到的方法是创建一个包含所有子类属性的显示类,但这不符合面向对象思想,求正确的解决方案。


解决方案
  • 确保DataTemplateSelector实现正确
    你的PlanPosDataTemplateSelector必须准确判断项的类型并返回对应模板,示例实现如下:

    public class PlanPosDataTemplateSelector : DataTemplateSelector
    {
        public DataTemplate AddressPos { get; set; }
        public DataTemplate DayPos { get; set; }
    
        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            return item switch
            {
                AddressPos => AddressPos,
                DayPos => DayPos,
                _ => base.OnSelectTemplate(item, container)
            };
        }
    }
    
  • 为ListView的ItemTemplate指定Selector
    必须确保ListView的ItemTemplate绑定到你的PosSelector,而非固定模板:

    <ListView ItemsSource="{Binding YourPlanPositionList}"
              ItemTemplate="{StaticResource PosSelector}">
        <!-- 其他ListView配置 -->
    </ListView>
    
  • 修复绑定上下文继承问题
    错误显示绑定上下文是PlannerViewModel,说明模板内的绑定未正确继承到列表项对象。可以在ViewCell内显式绑定上下文,或者检查父布局是否意外覆盖了绑定上下文:

    <ViewCell BindingContext="{Binding .}">
        <!-- 模板内容 -->
    </ViewCell>
    
  • 验证x:DataType的命名空间
    确认XAML中data:命名空间指向实体类所在的程序集和命名空间,例如:

    xmlns:data="clr-namespace:TripPlanner.Data;assembly=TripPlanner"
    
  • 修正AddressPos模板中的Name绑定
    AddressPos类中没有直接的Name属性,需修改为绑定Address对象的Name属性:

    <Label Text="{Binding Address.Name}"
           FontAttributes="Bold"
           FontSize="12"/>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:27:32