初めての Windows 8 クライアントを作成しています。非同期メソッドを使用してプロパティをロードしたのもこれが初めてなので、これが初歩的な質問である場合はご容赦ください。
私は WCF サービスを持っており、クライアント用のビジュアル スタジオの分割ページ テンプレートから開始しました (ただし、ほとんどすべてを置き換えます)。
「SplitPage」コードの背後にあるビューに直接データを取得すると、すべてが適切にロードされて表示されます。ただし、MVVM を使用しようとすると、バインドされたときにプロパティに項目がありません。WCF のため、データを取得するための非同期呼び出しが問題の原因ですか? プロパティを返す前にデータが戻っていることを確認する方法はありますか (プロパティ自体には非同期のラベルを付けることができないようです)。
これが私がしたことです:
テスト目的で、ListView を配置し (コードは listbox と表示されていますが、XAML では listview を使用しました)、OnNavigatedTo ハンドラーで呼び出される非同期メソッドとして次のコードを追加しました。
private async void GetUsersList()
{
ServiceClient client = new ServiceClient();
List<UserDTO> _users = (await client.GetUsersAsync()).ToList();
foreach(UserDTO user in _users)
{
UserListBox.Items.Add(new UserView(user));
}
TestStack.Children.Add(new UsersView());
}
これは正常に機能し、ページが読み込まれると、UserListBox に UserViews が含まれます。
次に、完全な MVVM パターンに入ろうとし、UsersViewModel と UsersView (複数) を、コンストラクターで、WCF サービスから取得した UserDTO の ObservableCollection を使用してプロパティ Users を初期化するリポジトリと共に作成しました。上記のメッセージの最後の行が行っているのは、ビューをページのスタックパネルに設定することです。
ビューとビューモデルはリソース ファイルにまとめられています。
<DataTemplate x:Key="vm:UsersViewModel">
<vw:UsersView />
</DataTemplate>
どうやら .Net 4.5 には DataTemplates の x:Type プロパティがないため、バインディングは私が慣れ親しんでいるものとは少し異なります。
データがロードされるリポジトリの部分は次のようになります。
private ObservableCollection<UserDTO> _users = new ObservableCollection<UserDTO>();
private ServiceClient _client = new ServiceClient();
public UserRepository()
{
GetUsers();
}
public async void GetUsers()
{
var tempList = await _client.GetUsersAsync();
foreach(UserDTO item in tempList)
{
_users.Add(item);
}
}
UsersViewModel のコンストラクターが行う唯一のことは、リポジトリのインスタンスを作成し、UserViewModel アイテムを UserViewModel の観察可能なコレクションにロードすることです。
public UsersViewModel()
{
_repo = new UserRepository();
foreach (UserDTO item in _repo.Users)
{
_users.Add(new UserViewModel(item.Id));
}
}
出力ステートメントをどこにでも配置しようとしましたが、SplitPage コード内の同じコードが WCF のフィード元のデータベースに既にあるテスト項目を返しても、プロパティ "getter" が空のリストを返すことを確認しました。コードが実行されるスレッドと同じくらい単純なものでしょうか? おそらく、SplitPage は UI スレッドで WCF への呼び出しを実行しているため、データの非同期呼び出しが返されるまでバインドは行われませんが、何らかの理由で MVVM を使用すると、データがバックグラウンド スレッドに読み込まれている間にすぐにデータ バインドが行われますか? もしそうなら、それが ObservableCollection であるという事実は、データが最終的にプロパティに表示されたときに UI に通知されるべきではありませんか?