Xamarin自定义Picker的FieldToDisplay绑定代码生效XAML不生效问题
问题原因
你在XAML中使用的FieldToDisplay="{Binding DisplayName}"语法的实际作用,是将FieldToDisplay属性绑定到当前控件BindingContext的DisplayName属性上,和你后台代码直接给FieldToDisplay赋值Binding实例的逻辑完全不一致,这是问题的核心:
- 后台代码写法是把
FieldToDisplay属性的值设为一个「绑定到列表项DisplayName属性的Binding对象」,符合你自定义控件的设计预期 - XAML的默认
{Binding}写法是把FieldToDisplay属性本身作为绑定目标,去读取上下文的DisplayName属性值,除非你的上下文返回的是BindingBase类型的对象,否则完全不符合预期;如果你的BindingContext上根本没有DisplayName属性,绑定会失败,属性值保持默认的null,自然不会触发FieldToDisplayChanged回调。
解决方案
方案1:修改XAML写法,直接传入Binding实例
使用x:Binding标记扩展直接创建Binding对象作为FieldToDisplay的属性值,完全对齐后台代码的逻辑:
FieldToDisplay="{x:Binding DisplayName}"
方案2:调整控件定义,适配常规XAML使用习惯
如果希望像原生Picker一样直接传属性名字符串,可以修改依赖属性的定义,使用起来更符合直觉:
// 修改属性类型为string public string FieldToDisplay { get => (string)GetValue(FieldToDisplayProperty); set => SetValue(FieldToDisplayProperty, value); } public static readonly BindableProperty FieldToDisplayProperty = BindableProperty.Create(nameof(FieldToDisplay), typeof(string), typeof(PickerField), propertyChanged: FieldToDisplayChanged); private static void FieldToDisplayChanged(BindableObject bindable, object oldValue, object newValue) { var matEntry = (PickerField)bindable; if (newValue is string fieldName) { // 内部自动创建Binding对象 matEntry.SelectField.ItemDisplayBinding = new Binding(fieldName); } }
修改后XAML中直接写字符串即可生效:
FieldToDisplay="DisplayName"
内容的提问来源于stack exchange,提问作者David Clarke
相关产品推荐
相关产品推荐

