我已经使用xaml创建了一个自定义选择器控件PCPicker
(考虑到将来的兼容性,请注意以下内容):
<Label x:Name="ControlLabel"
Style="{DynamicResource InputLabel}"
Text="{Binding LabelText}"/>
<Picker x:Name="ControlPicker"
ItemsSource="{Binding Src}"
Title="{Binding PlaceHolderText}"
Style="{DynamicResource PCPickerStyle}"
SelectedIndex="{Binding Index,Mode=TwoWay}"
SelectedItem="{Binding SelectedOption,Mode=OneWayToSource}"
/>
后面的代码如下:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PCPicker : ContentView
{
public static readonly BindableProperty LabelTextProperty =
BindableProperty.Create(
propertyName: nameof(LabelText),
returnType: typeof(string),
declaringType: typeof(PCPicker),
defaultValue: "",
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: LabelTextPropertyChanged);
public string LabelText
{
get { return GetValue(LabelTextProperty).ToString(); }
set { SetValue(LabelTextProperty, value); }
}
private static void LabelTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (PCPicker)bindable;
control.ControlLabel.Text = newValue.ToString();
}
public static readonly BindableProperty PlaceHolderTextProperty =
BindableProperty.Create(
propertyName: nameof(PlaceHolderText),
returnType: typeof(string),
declaringType: typeof(PCPicker),
defaultValue: "",
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: PlaceHolderTextPropertyChanged);
public string PlaceHolderText
{
get { return GetValue(PlaceHolderTextProperty).ToString(); }
set { SetValue(PlaceHolderTextProperty, value); }
}
private static void PlaceHolderTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (PCPicker)bindable;
control.ControlPicker.Title = newValue.ToString();
}
public static readonly BindableProperty SelectedOptionProperty =
BindableProperty.Create(
propertyName: nameof(SelectedOption),
returnType: typeof(object),
declaringType: typeof(PCPicker),
defaultValue: null,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: SelectedOptionChanged);
public object SelectedOption
{
get { return GetValue(SelectedOptionProperty); }
set { SetValue(SelectedOptionProperty, value); }
}
private static void SelectedOptionChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (PCPicker)bindable;
control.ControlPicker.SelectedItem = newValue;
}
public static readonly BindableProperty SrcProperty =
BindableProperty.Create(
propertyName: nameof(Src),
returnType: typeof(IList),
declaringType: typeof(PCPicker),
defaultValue: null,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: PickerSourceChanged);
public IList Src
{
get { return (IList)GetValue(SrcProperty); }
set { SetValue(SrcProperty, value); }
}
private static void PickerSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (PCPicker)bindable;
control.ControlPicker.ItemsSource = (IList)newValue;
}
public static readonly BindableProperty IndexProperty =
BindableProperty.Create(
propertyName: nameof(Index),
returnType: typeof(int),
declaringType: typeof(PCPicker),
defaultValue: -1,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: SelectedIndexChanged);
public int Index
{
get { return (int)GetValue(IndexProperty); }
set { SetValue(IndexProperty, value); }
}
private static void SelectedIndexChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (PCPicker)bindable;
control.ControlPicker.SelectedIndex = (int)newValue;
}
public BindingBase DisplayMember
{
get { return ControlPicker.ItemDisplayBinding; }
set { ControlPicker.ItemDisplayBinding = value; }
}
public PCPicker()
{
InitializeComponent();
}
}
用法:
<cc:PCPicker BindingContext="{x:Binding M}"
LabelText="* Location"
PlaceHolderText="Select Cat"
Src="{Binding Cats}"
SelectedOption="{Binding SelectedCat, Mode=TwoWay}"
Index="{Binding Position, Mode=TwoWay}"
DisplayMember="{Binding Name}"/>
通过上面的内容,我可以使Display Binding和ItemSource绑定起作用。但是,SelectedItem值绑定始终为null。我输入了SelectedIndex绑定作为测试,但它始终始终为0。我确保绑定Mode
为TwoWay
,但我仍然始终得到一个空的SelectedItem。任何帮助将不胜感激。
答案 0 :(得分:0)
您是否在ViewModel中实现了 INotifyPropertyChanged ?
ViewModels通常实现INotifyPropertyChanged接口,这意味着该类在其属性之一发生更改时会触发PropertyChanged事件。 Xamarin.Forms中的数据绑定机制将处理程序附加到此PropertyChanged事件,以便可以在属性更改时得到通知,并使目标保持新值。
因此您可以按照以下方式改进视频模型
public class MyViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
ObservableCollection<Cat> Cats { get; set; }
private Cat selectedCat;
public Cat SelectedCat
{
get
{
return selectedCat;
}
set
{
if (selectedCat != value)
{
selectedCat = value;
NotifyPropertyChanged();
// do something you want
}
}
}
private int position=0;
public int Position
{
get
{
return position;
}
set
{
if (position != value)
{
position = value;
NotifyPropertyChanged();
}
}
}
public MyViewModel()
{
//...
}
}