我正在嘗試設定一個串列視圖,在呼叫 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 視窗時沒有報告錯誤,也沒有報告系結錯誤,所以我不確定會出現什么問題?
編輯:我已經更新了我的代碼。我正在實施 NugetPackage Nito.Mvvm。如果我將我的 NoPicUsers 設定在 GetNoPicUsersAsync() 中,我會遇到相同的問題,即沒有資料系結到我的串列視圖,WPF 視窗大喊說在 UserModel 型別的物件上找不到 NoPicUsers 屬性。
So it appears that it thinks my ViewModel as a UserModel property instead of a List property. What would cause that?
In stepping through the code the task never seems to complete. The Task sits at Status = WaitingForActivation, Method = "{Null}", Result = "{Not yet computed}".
uj5u.com熱心網友回復:
這是一個執行緒問題,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 相同的執行緒上呼叫它,OnPropertyChanged則會觸發 UI 更新。因為視圖模型試圖在后臺執行緒上更新屬性,所以 UI 沒有收到通知,所以不知道它需要更新。
通過在后臺執行緒上進行繁重的作業,UI 在作業完成時保持回應。當任務回傳到 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>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/436198.html
標籤:c# wpf async-await azure-ad-graph-api
