MAUI嵌套BindableLayout初始化无显示,调试改XAML后正常
MAUI嵌套BindableLayout初始化无内容,调试修改XAML后正常显示的问题
在MAUI的XAML内容页中使用两层嵌套BindableLayout生成网格,初始化时页面无任何内容,但调试会话中修改XAML代码后内容正常显示。尝试过改用ObservableCollection、在Appearing事件中初始化数据,均未解决问题。
XAML代码
<ContentPage.Content> <StackLayout BindableLayout.ItemsSource="{Binding Tiles}" Orientation="Vertical" > <BindableLayout.ItemTemplate> <DataTemplate x:DataType="models:PipeTileRowCollection"> <StackLayout BindableLayout.ItemsSource="{Binding}" Orientation="Horizontal" > <BindableLayout.ItemTemplate> <DataTemplate x:DataType="models:PipeTile"> <Border Stroke="Gray" StrokeThickness="1" Padding="0" StrokeShape="Rectangle"> <Image Source="{Binding ImageSrc}" HeightRequest="62" WidthRequest="62" ></Image> </Border> </DataTemplate> </BindableLayout.ItemTemplate> </StackLayout> </DataTemplate> </BindableLayout.ItemTemplate> </StackLayout> </ContentPage.Content>
C# ViewModel代码
public partial class MainPageModel : ObservableObject { public MainPageModel() { var rows = new PipeTileRowCollection(); for (int i = 0; i < 4; i++) { var cols = new PipeTileCollection(); for (int j = 0; j < 4; j++) { cols.Add(new PipeTile()); } rows.Add(cols); } _Tiles = new PipeTileRowCollection(rows); } public ICommand TileTapCommand { get; set; } [ObservableProperty] private PipeTileRowCollection _Tiles; } public class PipeTileCollection : List<PipeTile> { } public class PipeTileRowCollection : List<PipeTileCollection> { public PipeTileRowCollection() { } public PipeTileRowCollection(PipeTileRowCollection rows) : base(rows) { } }
PipeTile类代码
public partial class PipeTile : ObservableObject { public PipeTile() { _ImageSrc = ImageSource.FromFile("straight.png"); } [ObservableProperty] private ImageSource _ImageSrc; }
页面代码
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new MainPageModel(); } }
问题原因及修复方案
核心问题
- 自定义集合类继承自
List<T>,未实现INotifyCollectionChanged接口,UI无法感知集合内容的变化。 - ViewModel构造函数中直接赋值私有字段
_Tiles,未触发由[ObservableProperty]生成的属性变更通知,UI无法得知数据已初始化。
修复步骤
- 将自定义集合改为继承
ObservableCollection<T>(已内置INotifyCollectionChanged实现):
public class PipeTileCollection : ObservableCollection<PipeTile> { } public class PipeTileRowCollection : ObservableCollection<PipeTileCollection> { public PipeTileRowCollection() { } public PipeTileRowCollection(PipeTileRowCollection rows) : base(rows) { } }
- 在ViewModel构造函数中使用自动生成的公共属性
Tiles赋值,确保触发属性变更通知:
public MainPageModel() { var rows = new PipeTileRowCollection(); for (int i = 0; i < 4; i++) { var cols = new PipeTileCollection(); for (int j = 0; j < 4; j++) { cols.Add(new PipeTile()); } rows.Add(cols); } // 使用公共属性赋值,触发属性变更通知 Tiles = new PipeTileRowCollection(rows); }
调试时修改XAML会触发UI重新渲染,此时绑定会重新读取数据,因此内容正常显示,但初始化阶段因缺少变更通知,UI未更新数据。
内容的提问来源于stack exchange,提问作者Mr W
相关产品推荐
相关产品推荐

