WPF ListView 未绑定到 ViewModel 属性
WPF ListView not Binding to ViewModel Property
我正在尝试设置一个列表视图,在调用 Azure GraphAPI 后将加载用户列表。数据绑定之前的一切都有效。对 Graph 的调用有效,返回的数据有效,都没有问题。
我在视图中设置了列表视图:
<ListView ItemsSource="{Binding NoPicUsers}" >
<ListView.View>
<GridView>
<GridViewColumn
Header="Display Name"
Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding NoPicUsers.DisplayName}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
对应的ViewModel有如下代码:
public class ContentPanelHomeViewModel : ViewModelBase
{
private List<UserModel> _noPicUsers;//NotifyTask<List<UserModel>> _noPicUsers;
public List<UserModel> NoPicUsers
{
get
{
return _noPicUsers;
}
set
{
_noPicUsers = value;
//OnPropertyChanged Method is in ViewModelBase
OnPropertyChanged("NoPicUsers");
}
}
public ContentPanelHomeViewModel()
{
//NoPicUsers = new NotifyTask<List<UserModel>>.Create(GetNoPicUsersAsync());
//NoPicUsers = NotifyTask.Create(GetNoPicUsersAsync);
var users = GetNoPicUsersAsync();
}
private async Task<List<UserModel>> GetNoPicUsersAsync()
{
GraphServiceClient graphClient = await GraphAPIServices.SignInAndInitGraph(AzureAppInfo.UserReadAll);
List<UserModel> users = new List<UserModel>();
var listOfUsers = await graphClient.Users
.Request()
.Filter("accountEnabled eq true")
.Select("displayname, id")
.GetAsync();
foreach (var user in listOfUsers)
{
UserModel azureUser = new UserModel();
azureUser.DisplayName = user.DisplayName;
azureUser.ObjectID = user.Id;
users.Add(azureUser);
}
NoPicUsers = users;
return users;
}
}
我的列表视图不显示任何数据,我不明白为什么。加载 WPF window 时没有报告错误,也没有报告绑定错误,所以我不确定会出现什么问题?
编辑:我更新了我的代码。我正在实施 NugetPackage Nito.Mvvm。如果我在 GetNoPicUsersAsync() 中设置我的 NoPicUsers,我会遇到同样的问题,即没有数据绑定到我的列表视图 WPF window 大喊说 NoPicUsers 属性 no found on object of Type UserModel.
所以它似乎将我的 ViewModel 视为 UserModel 属性 而不是列表 属性。什么会导致这种情况?
在逐步执行代码时,任务似乎从未完成。任务位于 Status = WaitingForActivation,Method =“{Null}”,Result =“{Not yet computed}”。
这是一个线程问题,UI 没有意识到所做的更改,因为 Task
正在单独的线程上调用,因为它没有被等待。
我建议使用视图模型引发的异步事件
public class ContentPanelHomeViewModel : ViewModelBase {
private List<UserModel> _noPicUsers;//NotifyTask<List<UserModel>> _noPicUsers;
public List<UserModel> NoPicUsers {
get {
return _noPicUsers;
}
set {
_noPicUsers = value;
//OnPropertyChanged Method is in ViewModelBase
OnPropertyChanged("NoPicUsers");
}
}
public ContentPanelHomeViewModel() {
starting += onStarting;
starting(this, EventArgs.Empty);
}
private event EventHandler starting = delegate { };
private async void onStarting(object sender, EventArgs args) {
starting -= onStarting; //optional
// the following runs on background thread
List<UserModel> users = await GetNoPicUsersAsync();
// returned to the UI thread
NoPicUsers = users; //notifies UI
}
private async Task<List<UserModel>> GetNoPicUsersAsync() {
GraphServiceClient graphClient = await GraphAPIServices.SignInAndInitGraph(AzureAppInfo.UserReadAll);
List<UserModel> users = new List<UserModel>();
var listOfUsers = await graphClient.Users
.Request()
.Filter("accountEnabled eq true")
.Select("displayname, id")
.GetAsync();
foreach (var user in listOfUsers) {
UserModel azureUser = new UserModel();
azureUser.DisplayName = user.DisplayName;
azureUser.ObjectID = user.Id;
users.Add(azureUser);
}
return users;
}
}
如果 UI 在与 UI 相同的线程上被调用,OnPropertyChanged
会触发 UI 更新。因为试图在后台线程上更新 属性 的视图模型 UI 没有收到通知,所以不知道它需要更新。
通过在后台线程上完成繁重的工作,UI 在工作完成时保持响应。当任务 returns 到 UI 线程时,属性 可以更新,因此 UI 可以接收事件触发器以更新自身。
UI 中声明的绑定也存在问题。单元格模板需要绑定到项目的属性,而不是顶层属性
<ListView ItemsSource="{Binding NoPicUsers}" >
<ListView.View>
<GridView>
<GridViewColumn
Header="Display Name"
Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
我正在尝试设置一个列表视图,在调用 Azure GraphAPI 后将加载用户列表。数据绑定之前的一切都有效。对 Graph 的调用有效,返回的数据有效,都没有问题。
我在视图中设置了列表视图:
<ListView ItemsSource="{Binding NoPicUsers}" >
<ListView.View>
<GridView>
<GridViewColumn
Header="Display Name"
Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding NoPicUsers.DisplayName}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
对应的ViewModel有如下代码:
public class ContentPanelHomeViewModel : ViewModelBase
{
private List<UserModel> _noPicUsers;//NotifyTask<List<UserModel>> _noPicUsers;
public List<UserModel> NoPicUsers
{
get
{
return _noPicUsers;
}
set
{
_noPicUsers = value;
//OnPropertyChanged Method is in ViewModelBase
OnPropertyChanged("NoPicUsers");
}
}
public ContentPanelHomeViewModel()
{
//NoPicUsers = new NotifyTask<List<UserModel>>.Create(GetNoPicUsersAsync());
//NoPicUsers = NotifyTask.Create(GetNoPicUsersAsync);
var users = GetNoPicUsersAsync();
}
private async Task<List<UserModel>> GetNoPicUsersAsync()
{
GraphServiceClient graphClient = await GraphAPIServices.SignInAndInitGraph(AzureAppInfo.UserReadAll);
List<UserModel> users = new List<UserModel>();
var listOfUsers = await graphClient.Users
.Request()
.Filter("accountEnabled eq true")
.Select("displayname, id")
.GetAsync();
foreach (var user in listOfUsers)
{
UserModel azureUser = new UserModel();
azureUser.DisplayName = user.DisplayName;
azureUser.ObjectID = user.Id;
users.Add(azureUser);
}
NoPicUsers = users;
return users;
}
}
我的列表视图不显示任何数据,我不明白为什么。加载 WPF window 时没有报告错误,也没有报告绑定错误,所以我不确定会出现什么问题?
编辑:我更新了我的代码。我正在实施 NugetPackage Nito.Mvvm。如果我在 GetNoPicUsersAsync() 中设置我的 NoPicUsers,我会遇到同样的问题,即没有数据绑定到我的列表视图 WPF window 大喊说 NoPicUsers 属性 no found on object of Type UserModel.
所以它似乎将我的 ViewModel 视为 UserModel 属性 而不是列表 属性。什么会导致这种情况?
在逐步执行代码时,任务似乎从未完成。任务位于 Status = WaitingForActivation,Method =“{Null}”,Result =“{Not yet computed}”。
这是一个线程问题,UI 没有意识到所做的更改,因为 Task
正在单独的线程上调用,因为它没有被等待。
我建议使用视图模型引发的异步事件
public class ContentPanelHomeViewModel : ViewModelBase {
private List<UserModel> _noPicUsers;//NotifyTask<List<UserModel>> _noPicUsers;
public List<UserModel> NoPicUsers {
get {
return _noPicUsers;
}
set {
_noPicUsers = value;
//OnPropertyChanged Method is in ViewModelBase
OnPropertyChanged("NoPicUsers");
}
}
public ContentPanelHomeViewModel() {
starting += onStarting;
starting(this, EventArgs.Empty);
}
private event EventHandler starting = delegate { };
private async void onStarting(object sender, EventArgs args) {
starting -= onStarting; //optional
// the following runs on background thread
List<UserModel> users = await GetNoPicUsersAsync();
// returned to the UI thread
NoPicUsers = users; //notifies UI
}
private async Task<List<UserModel>> GetNoPicUsersAsync() {
GraphServiceClient graphClient = await GraphAPIServices.SignInAndInitGraph(AzureAppInfo.UserReadAll);
List<UserModel> users = new List<UserModel>();
var listOfUsers = await graphClient.Users
.Request()
.Filter("accountEnabled eq true")
.Select("displayname, id")
.GetAsync();
foreach (var user in listOfUsers) {
UserModel azureUser = new UserModel();
azureUser.DisplayName = user.DisplayName;
azureUser.ObjectID = user.Id;
users.Add(azureUser);
}
return users;
}
}
如果 UI 在与 UI 相同的线程上被调用,OnPropertyChanged
会触发 UI 更新。因为试图在后台线程上更新 属性 的视图模型 UI 没有收到通知,所以不知道它需要更新。
通过在后台线程上完成繁重的工作,UI 在工作完成时保持响应。当任务 returns 到 UI 线程时,属性 可以更新,因此 UI 可以接收事件触发器以更新自身。
UI 中声明的绑定也存在问题。单元格模板需要绑定到项目的属性,而不是顶层属性
<ListView ItemsSource="{Binding NoPicUsers}" >
<ListView.View>
<GridView>
<GridViewColumn
Header="Display Name"
Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>