Xamarin Android Picker绑定问题到ObservableCollection



我有一个简单的Xamarin.Forms项目,带有Picker

我的视图绑定到从INotifyPropertyChanged继承的视图模型。

我定义了一个类似于的ObservableCollection

public ObservableCollection<User> UserList { get; set; }

HTTP客户端Get方法填充:

UserList = JsonConvert.DeserializeObject<ObservableCollection<User>>(s);

我已经验证了UserList已经填充了预期的数据。

这是我的选择器:

<Picker Title="User"
Grid.Row="0"
Grid.Column="0"
ItemsSource="{Binding UserList}"
ItemDisplayBinding="{Binding UserName}"
SelectedItem="{Binding UserSelectedItem}"/>

这是我的SelectedItem绑定属性:

public User UserSelectedItem { get; set; }

我没有使用OnPropertyChangedUserSelectedItem

问题是:我在Picker中没有得到任何值,尽管我已经验证了UserList中确实有预期的数据

编辑

我修改了ObservableCollection以使用OnPropertyChanged:

private ObservableCollection<User> _userList;
public ObservableCollection<User> UserList
{
get
{
return _userList;
}
set
{
_userList = value;
OnPropertyChanged(nameof(UserList));
}
}

但数据仍然没有到达拾取器。。。

EDIT 2我还是想不通。这是我的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" 
x:Class="PTSX.Views.JoinCrew">
<ContentPage.Content>
<StackLayout>
<Label Text="Join a Crew" 
HorizontalOptions="CenterAndExpand" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="200"/>
<RowDefinition Height="200"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>


<Picker x:Name ="UserPicker" 
Title="User"
Grid.Row="0"
Grid.Column="0"
ItemsSource="{Binding UserList}"
ItemDisplayBinding="{Binding UserName}"
SelectedItem="{Binding UserSelectedItem}"/>

<Picker x:Name="CrewPicker" 
Title="Crew"
Grid.Row="1"
Grid.Column="0"
ItemsSource="{Binding CrewList}"
ItemDisplayBinding="{Binding CrewName}"
SelectedItem="{Binding CrewSelectedItem}"/>
<Button x:Name="buttonJoinCrew"
Text="Join"
Grid.Row="2"
Grid.Column="0"
Command="{Binding JoinCrewCommand}"/>
<Button x:Name="buttonCreateCrew"
Text="Add Crew"
Grid.Row="3"
Grid.Column="0"
Command="{Binding AddCrewCommand}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>

这是我的XAML代码背后:

public partial class JoinCrew : ContentPage
{
private JoinCrewViewModel viewModel { get; set; }
public JoinCrew()
{
InitializeComponent();
viewModel = new JoinCrewViewModel();
BindingContext = viewModel;
}
}

这是我的视图模型:

public class JoinCrewViewModel : INotifyPropertyChanged
{
#region Fields
private string _crewName;
private string _crewId;
private string _userName;
private string _userId;
private IList<User> _userList;
private IList<DailyCrew> _crewList;
private User _userSelectedItem;
private DailyCrew _crewSelectedItem;
#endregion
#region Properties
public string CrewName
{
get
{
return _crewName;
}
set
{
_crewName = value;
OnPropertyChanged();
}
}
public string CrewId
{
get
{
return _crewId;
}
set
{
_crewId = value;
OnPropertyChanged();
}
}
public string UserName
{
get
{
return _userName;
}
set
{
_userName = value;
OnPropertyChanged();
}
}
public string UserId
{
get
{
return _userId;
}
set
{
_userId = value;
OnPropertyChanged();
}
}
public DailyCrew CrewSelectedItem
{
get => _crewSelectedItem;
set
{
_crewSelectedItem = value;
OnPropertyChanged();
}
}
public User UserSelectedItem
{
get => _userSelectedItem;
set
{
_userSelectedItem = value;
OnPropertyChanged();
}
}
public IList<DailyCrew> CrewList
{
get
{
return _crewList;
}
set
{
_crewList = value;
OnPropertyChanged();
}
}
public IList<User> UserList
{
get
{
return _userList;
}
set
{
_userList = value;
OnPropertyChanged();
}
}
#endregion
#region Events
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var propertyChanged = PropertyChanged;
propertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Delegates
public Command JoinCrewCommand { get; }
public Command AddCrewCommand { get; }
#endregion
#region Contructor
public JoinCrewViewModel()
{
JoinCrewCommand = new Command(JoinCrewAction);
AddCrewCommand = new Command(AddCrewAction);
async Task FillUsersAsync();
}
private bool CanExecuteCommand(object commandParameter)
{
return true;
}
#endregion
#region Commands
private async void JoinCrewAction()
{
await JoinCrew();
}
#endregion
#region Private Methods

private async Task<IList<User>> FillUsersAsync()
{
IList<User> result = null;
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync($"https://xxx/api/mobile/getuserslist");
if (response.IsSuccessStatusCode)
{
string s = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<IList<User>>(s);
}
}
return result;
}
}

我可以像以前一样确认,我有数据通过Http客户端返回到我的IList

我不明白为什么皮克尔没有人。这似乎应该很容易做到。

我已经编写了一个简单的示例,它非常适合我。

通过点击按钮,将加载绑定到选取器的ItemsSource的属性,并且由于OnPropertyChanged((调用,将通知选取器集合已更改,并且它将正确加载值。

请看一下样品,如果你仍然有问题,请分享更多细节。。。

主页.xaml.cs

using System;
using Xamarin.Forms;
namespace PickerOC
{
public partial class MainPage : ContentPage
{
MainPageViewModel viewModel { get; set; }
public MainPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
viewModel = new MainPageViewModel();
BindingContext = viewModel;
}
private void Button_Clicked(object sender, EventArgs e)
{
viewModel.PickerData = new System.Collections.ObjectModel.ObservableCollection<UserX>()
{
new UserX("John L."), new UserX("Paul M."), new UserX("George H."), new UserX("Ringo S.")
};
}
}
}

主页.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"
x:Class="PickerOC.MainPage">
<StackLayout>
<Picker ItemsSource="{Binding PickerData}"
ItemDisplayBinding="{Binding UserName}"/>
<Button Text="Load Picker Data!"
Clicked="Button_Clicked"/>
</StackLayout>
</ContentPage>

ViewModel

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace PickerOC
{
class MainPageViewModel : INotifyPropertyChanged
{
private ObservableCollection<UserX> _PickerData;
public ObservableCollection<UserX> PickerData
{ 
get => _PickerData;
set
{
_PickerData = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = "")
{
var propertyChanged = PropertyChanged;
propertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class UserX
{
public UserX(String name)
{
UserName = name;
}
public String UserName { get; set; }
}
}

我使用了您发布的代码,并使其在我这边工作。

注意,我用一个简单的异步函数模拟了FillUsersAsync,该函数等待五秒钟,然后返回一个Users集合。

XAML

<ContentPage.Content>
<StackLayout>
<Label Text="Join a Crew" 
HorizontalOptions="CenterAndExpand" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="200"/>
<RowDefinition Height="200"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>

<Picker x:Name ="UserPicker" 
Title="User"
Grid.Row="0"
Grid.Column="0"
ItemsSource="{Binding UserList}"
ItemDisplayBinding="{Binding UserName}"
SelectedItem="{Binding UserSelectedItem}"/>
<Picker x:Name="CrewPicker" 
Title="Crew"
Grid.Row="1"
Grid.Column="0"
ItemsSource="{Binding CrewList}"
ItemDisplayBinding="{Binding CrewName}"
SelectedItem="{Binding CrewSelectedItem}"/>
<Button x:Name="buttonJoinCrew"
Text="Join"
Grid.Row="2"
Grid.Column="0"
Command="{Binding JoinCrewCommand}"/>
<Button x:Name="buttonCreateCrew"
Text="Add Crew"
Grid.Row="3"
Grid.Column="0"
Command="{Binding AddCrewCommand}"/>
</StackLayout>
</ContentPage.Content>

代码隐藏

using Xamarin.Forms;
namespace PickerOC
{
public partial class MainPage : ContentPage
{
MainPageViewModel viewModel { get; set; }
public MainPage()
{
InitializeComponent();
viewModel = new MainPageViewModel();
BindingContext = viewModel;
}

}
}

查看模型

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace PickerOC
{
class MainPageViewModel : INotifyPropertyChanged
{
#region Fields
private string _crewName;
private string _crewId;
private string _userName;
private string _userId;
private IList<User> _userList;
private IList<DailyCrew> _crewList;
private User _userSelectedItem;
private DailyCrew _crewSelectedItem;
#endregion
#region Properties
public string CrewName
{
get
{
return _crewName;
}
set
{
_crewName = value;
OnPropertyChanged();
}
}
public string CrewId
{
get
{
return _crewId;
}
set
{
_crewId = value;
OnPropertyChanged();
}
}
public string UserName
{
get
{
return _userName;
}
set
{
_userName = value;
OnPropertyChanged();
}
}
public string UserId
{
get
{
return _userId;
}
set
{
_userId = value;
OnPropertyChanged();
}
}
public DailyCrew CrewSelectedItem
{
get => _crewSelectedItem;
set
{
_crewSelectedItem = value;
OnPropertyChanged();
}
}
public User UserSelectedItem
{
get => _userSelectedItem;
set
{
_userSelectedItem = value;
OnPropertyChanged();
}
}
public IList<DailyCrew> CrewList
{
get
{
return _crewList;
}
set
{
_crewList = value;
OnPropertyChanged();
}
}
public IList<User> UserList
{
get
{
return _userList;
}
set
{
_userList = value;
OnPropertyChanged();
}
}
#endregion
#region Events
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var propertyChanged = PropertyChanged;
propertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Delegates
public Command JoinCrewCommand { get; }
public Command AddCrewCommand { get; }
#endregion
#region Contructor
public MainPageViewModel()
{
JoinCrewCommand = new Command(JoinCrewAction);
AddCrewCommand = new Command(AddCrewAction);
Task.Run(async () => UserList = await FillUsersAsync());
//async Task FillUsersAsync();
}
private bool CanExecuteCommand(object commandParameter)
{
return true;
}
#endregion
#region Commands
private async void AddCrewAction()
{
await Task.Delay(1000);
}
private async void JoinCrewAction()
{
await Task.Delay(1000);
}
#endregion
#region Private Methods

private async Task<IList<User>> FillUsersAsync()
{
IList<User> result = null;
//using (var client = new HttpClient())
//{
//    HttpResponseMessage response = await client.GetAsync($"https://xxx/api/mobile/getuserslist");
//    if (response.IsSuccessStatusCode)
//    {
//        string s = await response.Content.ReadAsStringAsync();
//        result = JsonConvert.DeserializeObject<IList<User>>(s);
//    }
//}
await Task.Delay(5000);
result = new List<User>()
{
new User() {UserName = "John L."},
new User() {UserName = "Paul M."},
};
return result;
}
#endregion
}
public class User
{
public string UserID { get; set; }
public string UserName { get; set; }
}
public class DailyCrew
{
public string CrewId { get; set; }
public string CrewName { get; set; }
}
}

我使用了您发布的代码,并让它在我这边为用户选择器工作。

ViewModel.cs

public class JoinCrewViewModel : INotifyPropertyChanged
{
#region Fields
private ObservableCollection<User> _userList;
private User _userSelectedItem;
#endregion
#region Properties
public User UserSelectedItem
{
get => _userSelectedItem;
set
{
_userSelectedItem = value;
OnPropertyChanged();
}
}

public ObservableCollection<User> UserList
{
get
{
return _userList;
}
set
{
_userList = value;
OnPropertyChanged();
}
}
#endregion
#region Events
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var propertyChanged = PropertyChanged;
propertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion

#region Contructor
public JoinCrewViewModel()
{
FillUsersAsync();
}
#endregion

private async Task<ObservableCollection<User>> FillUsersAsync()
{
_userList = new ObservableCollection<User>() { 
new User()
{
UserName = "test",
UserId = "1"
},
new User()
{
UserName = "test1",
UserId = "2"
},
new User()
{
UserName = "test2",
UserId = "3"
},
new User()
{
UserName = "test3",
UserId = "4"
},
new User()
{
UserName = "test3",
UserId = "5"
}
};
_userSelectedItem = _userList[2];
return _userList;
}
}
public class User
{
public string UserName { get; set; }
public string UserId { get; set; }
}

主页.xaml

<StackLayout>
<Label Text="Join a Crew" 
HorizontalOptions="CenterAndExpand" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="200"/>
<RowDefinition Height="200"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>

<Picker x:Name ="UserPicker" 
Title="User"
Grid.Row="0"
Grid.Column="0"
ItemsSource="{Binding UserList}"
ItemDisplayBinding="{Binding UserName}"
SelectedItem="{Binding UserSelectedItem}"/>
</StackLayout>

相关内容

  • 没有找到相关文章

最新更新