Xamarin.Forms自定义Picker控件ItemsSource绑定失效求助
Let's break down why your HitPicker isn't working as expected—this is a super common pitfall when building custom controls with Xamarin.Forms!
The Root Cause
You set BindingContext = this; in the HitPicker constructor. This overrides the external BindingContext (your ViewModel) that's set when you use the control in your page. So when you bind ItemsSource="{Binding MonkeyList}", the control is looking for a MonkeyList property on the HitPicker itself instead of your ViewModel—hence why the ViewModel's getter never gets called, and OnItemsSourceChanged never triggers.
Step-by-Step Fixes
1. Remove the Hardcoded BindingContext
First, delete this line from your HitPicker constructor—it's the main culprit:
BindingContext = this;
2. Update the Custom Control's XAML to Use RelativeSource Binding
Instead of relying on the control's BindingContext, explicitly bind the internal Picker properties to the HitPicker control itself using RelativeSource:
<Picker x:Name="PickerField" HeightRequest="46" TitleColor="{Binding TitleColor, Source={RelativeSource AncestorType={x:Type controls:HitPicker}}}" TextColor="{Binding TextColor, Source={RelativeSource AncestorType={x:Type controls:HitPicker}}}" BackgroundColor="{Binding BackgroundColor, Source={RelativeSource AncestorType={x:Type controls:HitPicker}}}" Unfocused="Handle_Unfocused" Focused="Handle_Focused" SelectedItem="{Binding SelectedItem, Source={RelativeSource AncestorType={x:Type controls:HitPicker}}}" ItemsSource="{Binding ItemsSource, Source={RelativeSource AncestorType={x:Type controls:HitPicker}}}"> </Picker> *(Ensure your XAML has the correct XML namespace for `controls` declared at the top.)* #### 3. Refine the BindableProperty Definition (Best Practice) Use `nameof(ItemsSource)` instead of a string literal to avoid typos, and adjust the binding mode since collection properties rarely need TwoWay binding: ```csharp public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create( nameof(ItemsSource), typeof(List<string>), typeof(HitPicker), default(List<string>), BindingMode.OneWay, propertyChanged: OnItemsSourceChanged); public List<string> ItemsSource { get => (List<string>)GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value); }
4. Hardened OnItemsSourceChanged Method
Add null checks to prevent unexpected crashes:
private static void OnItemsSourceChanged(BindableObject bindable, object oldvalue, object newvalue) { var hitPicker = bindable as HitPicker; var picker = hitPicker?.PickerField; if (picker == null) return; picker.Items.Clear(); var newList = newvalue as List<string>; if (newList != null) { foreach (var item in newList) { picker.Items.Add(item); } } }
Verify Your Setup
Your page's XAML usage is already correct, and you confirmed the page's BindingContext points to your ViewModel—perfect. After applying these fixes, the ItemsSource binding will correctly connect to your ViewModel's MonkeyList, OnItemsSourceChanged will trigger when the list loads, and the picker dialog will display your monkey items as expected.
内容的提问来源于stack exchange,提问作者TameemHabash

