如何在Xamarin.Forms中从CarouselView传递对象至自定义控件?
问题:CarouselView绑定正常,但CustomControl的Item属性始终为null
我使用CarouselView绑定ViewModel中的MyList集合,CarouselView可以正常左右滚动显示列表项,但自定义控件CustomControl的Item属性无法接收到对应的ListItem实例,始终返回null。
相关代码
XAML页面代码
<ContentPage.Content> <CarouselView ItemsSource="{Binding MyList}"> <CarouselView.ItemTemplate> <DataTemplate> <StackLayout> <controls:CustomControl Item="{Binding}"/> </StackLayout> </DataTemplate> </CarouselView.ItemTemplate> </CarouselView> </Grid> </ContentPage.Content>
HomeView代码
[XamlCompilation(XamlCompilationOptions.Compile)] public partial class HomeView : ContentPage { private ListContainer vm; public HomeView() { InitializeComponent(); Task.Run(async () => { vm = DiContainer.Resolve<ListContainer>(); await vm.Initialise(); Device.BeginInvokeOnMainThread(() => { this.BindingContext = vm; }); }); } }
CustomControl代码
[XamlCompilation(XamlCompilationOptions.Compile)] public partial class CustomControl : ContentView { public static readonly BindableProperty ItemProperty = BindableProperty.Create(nameof(Item), typeof(ListItem), typeof(CustomControl), default(ListItem),BindingMode.TwoWay); public ListItem Item { get => (ListItem)GetValue(ItemProperty); set => SetValue(ItemProperty, value); } public CustomControl () { InitializeComponent (); } }
解决方案
避免覆盖CustomControl的BindingContext
如果CustomControl的构造函数或XAML中手动设置了BindingContext = this;,会覆盖从CarouselView ItemTemplate传递过来的上下文,导致{Binding}无法指向当前的ListItem。若需绑定自定义控件自身的属性,改用RelativeSource绑定,例如:<!-- 在CustomControl的XAML中绑定自身Item属性 --> <Label Text="{Binding Item.Name, RelativeSource={RelativeSource Self}}"/>调整BindableProperty的绑定模式
由于是父级向自定义控件单向传递数据,无需使用TwoWay模式,改为OneWay更合理,减少不必要的绑定开销:public static readonly BindableProperty ItemProperty = BindableProperty.Create( nameof(Item), typeof(ListItem), typeof(CustomControl), default(ListItem), BindingMode.OneWay);确保集合类型为ObservableCollection
将MyList的类型从List<ListItem>改为ObservableCollection<ListItem>,这样集合的变化能及时通知UI,避免因集合更新不及时导致的绑定问题。调试绑定错误
在App.xaml.cs中开启绑定调试日志,查看输出窗口的绑定错误信息,直接定位问题:#if DEBUG Microsoft.Maui.Controls.Log.Listeners.Add(new Microsoft.Maui.Controls.DebugLogger()); #endif调整ViewModel初始化时机
可将ViewModel的初始化逻辑移至OnAppearing方法中,确保页面显示前绑定上下文已设置完成:protected override async void OnAppearing() { base.OnAppearing(); vm = DiContainer.Resolve<ListContainer>(); await vm.Initialise(); this.BindingContext = vm; }
内容的提问来源于stack exchange,提问作者Renma
相关产品推荐
相关产品推荐

