我遇到的问题是ContentPageView中的标签没有像不使用ContentView时那样显示选择的值。我尝试了不同的方法,但似乎没有任何效果,有什么建议可以告诉我,我可能遗漏了什么?
注:简化的代码删除了不必要的参数。这是一个经常被重复使用的自定义控件,它有更多的组件,与手头这个问题无关
PickerContentView.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.Core.Views.Templates.PickerContentView">
<ContentView.Content>
<Grid>
<Picker x:Name="CustomPicker" />
</Grid>
</ContentView.Content>
</ContentView>
PickerContentView.xaml.cs
namespace Test.Core.Views.Templates
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PickerContentView: ContentView
{
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(PickerContentView), string.Empty);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(PickerContentView), default(IList));
public static readonly BindableProperty ItemDisplayBindingProperty = BindableProperty.Create(nameof(ItemDisplayBinding), typeof(string), typeof(PickerContentView), string.Empty);
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(nameof(SelectedItem1), typeof(object), typeof(PickerContentView), default);
public string Title
{
get => (string)GetValue(PickerContentView.TitleProperty);
set => SetValue(PickerContentView.TitleProperty, value);
}
public IList ItemsSource
{
get => (IList)GetValue(PickerContentView.ItemsSourceProperty);
set => SetValue(PickerContentView.ItemsSourceProperty, value);
}
public string ItemDisplayBinding
{
get => (string)GetValue(PickerContentView.ItemDisplayBindingProperty);
set => SetValue(PickerContentView.ItemDisplayBindingProperty, value);
}
public object SelectedItem1
{
get => GetValue(PickerContentView.SelectedItemProperty);
set => SetValue(PickerContentView.SelectedItemProperty, value);
}
public PickerContentView()
{
InitializeComponent();
}
protected override void OnPropertyChanged(string propertyName)
{
base.OnPropertyChanged(propertyName);
if (propertyName == TitleProperty.PropertyName)
CustomPicker.Title = Title;
if (propertyName == ItemsSourceProperty.PropertyName)
CustomPicker.ItemsSource = ItemsSource;
if (propertyName == ItemDisplayBindingProperty.PropertyName)
CustomPicker.ItemDisplayBinding = new Binding(ItemDisplayBinding);
if (propertyName == SelectedItemProperty.PropertyName)
CustomPicker.SelectedItem = SelectedItem1;
}
}
}
ContentPageView.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModelBase="clr-Test.Core.ViewModels.Base;assembly=Test.Core"
xmlns:templates="clr-Test.Core.Views.Templates;assembly=Test.Core"
x:Class="Test.Core.Views.ContentPage"
viewModelBase:ViewModelLocator.AutoWireViewModel="true"
Title="Test">
<ContentPage.Content>
<ScrollView>
<StackLayout>
<templates:PickerContentView Title="Picker List"
ItemsSource="{Binding ListObjects}"
ItemDisplayBinding="Name"
SelectedItem1="{Binding CustomObject, Mode=TwoWay}" />
<Label Text="{Binding CustomObject.Name}" />
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
内容页视图.xaml.cs
namespace Test.Core.Views
{
public partial class ContentPageView: ContentPage
{
public ContentPageView()
{
InitializeComponent();
}
}
}
ContentPageView.xaml.cs
namespace Test.Core.ViewModels
{
public class CustomPageViewModel : ViewModelBase
{
private readonly IService _service;
private ObservableCollection<CustomObject> _listObjects;
private CustomObject _customObject;
public ObservableCollection<CustomObject> ListObjects
{
get { return _listObjects; }
set
{
_listObjects= value;
RaisePropertyChanged(() => ListObjects);
}
}
public CustomObject CustomObject
{
get { return _customObject; }
set
{
_customObject= value;
RaisePropertyChanged(() => CustomObject);
}
}
public CustomPageViewModel(IService service)
{
_service = service;
}
public override async Task InitializeAsync()
{
IsBusy = true;
ListObjects= await _service.GetListObjectsAsync();
IsBusy = false;
}
}
}
你需要实现 propertyChnaged
中的可绑定属性的委托。PickerContentView
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(propertyName: nameof(SelectedItem1),
returnType: typeof(object),
declaringType: typeof(PickerContentView),
defaultValue: default,
propertyChanged: SelectedItem1Changed);
private static void SelectedItem1Changed(BindableObject bindable, object oldValue, object newValue)
{
var thisView = bindable as PickerContentView;
thisView.CustomPicker.SelectedItem = newValue ;
}
此外,看起来像绑定似乎是错误的,SelectedItem应该在绑定的ItemsSource中找到,在你的情况下,看起来你是分配给一个新的对象。CustomPageViewModel.CustomObject
相对于 CustomPageViewModel.ListObjects[n]
如果对象是不同的,可能就不会成功。然后在 SelectedItem1Changed
便是
private static void SelectedItem1Changed(BindableObject bindable, object oldValue, object newValue)
{
var thisView = bindable as PickerContentView;
var temp = thisView.CustomPicker.ItemsSource.Cast<object>().FirstOrDefault(x=>x == newObject);
if(temp != null)
thisView.CustomPicker.SelectedItem = temp ;
}
我建议你加上 SelectIndex
的属性,以 PickerContentView