2017-06-16 5 views
-5

私のUWPアプリケーションでは、API呼び出しから返されたデータに基づいてUIを更新しています。 MyPage私はAPI呼び出しから戻さデータを表示ページで、これは私がそれを行う方法です。非同期UWPのビューの更新に関する待機の問題

public sealed partial class MyPage : Page 
{ 
    private MyViewModel _viewModel; 
    private MyApiResponse _result; 
    private string _documentId; 

    public DocumentDetailsPage() 
    { 
     this.InitializeComponent();    
     _viewModel = new MyViewModel();    
    } 

    protected async override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     base.OnNavigatedTo(e);  
     _documentId = (string)e.Parameter; 
     await GetDocumentDetails(); 
    } 

    private async Task GetDocumentDetails() 
    { 
     //THIS WORKS, BUT USING await INSTESD OF .Result DOESN'T UPDATE THE VIEW 
     _result = new MyApiCall(_documentId).GetResponseAsync().Result; 
     PrepareViewModel();   
    } 

    private void PrepareViewModel() 
    {  
     viewModel.Type = _result.response.type; 
     viewModel.VolumeNumber = _result.response.volumeNumber; 
    } 
} 

これは、APIへのHTTP-POSTリクエストを行うクラスです。

public class MyApiCAll 
    { 
     ... 
     ... 

     public async Task<MyApiResponse> GetResponseAsync() 
     { 
      MyApiResponse responseObject; 
      using(HttpClient client = new HttpClient()) 
      { 
       client.DefaultRequestHeaders.TryAddWithoutValidation("ABC", ABC); 
       var response = await _client.PostAsync("someURL", null).ConfigureAwait(false); 
       var responseJson = await response.Content.ReadAsStringAsync(); 
       responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<MyApiResponse>(responseJson);   
      } 
      return responseObject; 
     } 
    } 

そして、ここに私の見解です:

私はメソッド呼び出しから Resultを削除するとのawait李を追加するときにこれがUIので、そのブロックを除いて完全に正常に動作し
<StackPanel Style="{StaticResource ContainerStackPanel}" 
      Visibility="{x:Bind viewModel.Type, Converter={StaticResource ConverterNameHere}, Mode=OneWay}"> 
    <TextBlock Text="ABC"/> 
    <TextBlock Text="{x:Bind viewModel.Type, Mode=OneWay}"/> 
</StackPanel> 

<StackPanel Style="{StaticResource ContainerStackPanel}" 
      Visibility="{x:Bind viewModel.volumeNumber, Converter={StaticResource ConverterNameHere}, Mode=OneWay}"> 
    <TextBlock Text="ABC"/> 
    <TextBlock Text="{x:Bind viewModel.volumeNumber, Mode=OneWay}"/> 
</StackPanel> 

_result = await new DocumentDetailsApiCall(_documentId).GetResponseAsync(); 

私のUIにはバインドされた値が表示されず、空白のままです。 viewModelプロパティが更新されることを確認できます。示唆したように、私は(私はそれを実装しようとした、anytingを変更していない)私のViewModelのプロパティに

UPDATEINotifyPropertyChangedを実装していないです

、私は私のViewModelとHERESに私のViewModelクラス

INPCを追加しました
class MyViewModel : INotifyPropertyChanged 
{ 
    private string _type; 
    public string Type 
    { 
     get { return _type; } 
     set 
     { 
      _type = value; 
      this.OnPropertyChanged(); 
     } 
    } 

    private string _volumeNumber; 
    public string VolumeNumber 
    { 
     get { return _volumeNumber; } 
     set 
     { 
      _volumeNumber = value; 
      this.OnPropertyChanged(); 
     } 
    }   

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    public void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

問題が残っていますが、私はawait演算子を使用できません。 .Resultはまだ動作します。

+3

INPCを使用していない限り、間違いなく*動作しません。おそらく実装が間違っていたでしょうか?また、 xとは何ですか?単純なバインドをバインドしますか? – BradleyDotNET

+0

1)ビューモデルは、ビューを更新するために 'INotifyPropertyChanged'を実装する必要があります。それが彼らの持つ全目的です。 2)ブロッキングコール '.Result'を削除する3)ビューで使用されているプロパティ名がビューモデルのプロパティ名と一致することを確認する。それがtypoでない限り、 'volumeNumber'と同じです。 – Nkosi

+3

問題を確実に再現する[mcve]がなければ、実際の回答は不可能です。しかし '{x:Bind} 'のデフォルトモードは' OneTime'です。バインドされた 'Text'プロパティに対して' OneWay'を正しく設定しましたが、 'Visibility'プロパティは正しく設定していません。したがって、初期値のバインド値が設定されると、プロパティ値の変更は可視性に影響しません。 –

答えて

3

Bindings.Update()を呼び出すと、バインディング式は正しいはずですが、何らかの形でプロパティ変更通知が失敗します。

私は本当にここで何が悪かったのかを推測することができますが、Bindings.Update()を使用しなければならない時に説明するつもりはない、とあなたはINPC + OneWayバインディングを使用する必要があるとき。あなたのUIはほとんど新しいデータで更新する必要がない場合

Bindings.Update()は、伝統的な結合とは異なり、x:Bindでのみ利用可能です、あなたはあなたの特性を持つINPCを実装する必要はありません、実際には、それは実際にははるかに安いとOneTimeをやってよりパフォーマンスですバインディング(Bindings.Update()を呼び出して)INPCOneWayバインディングを実装するよりも。

ので、以下はx:Bindで動作します - ボタンがクリックされると

<TextBlock Text="{x:Bind MyText}" Style="{StaticResource SubheaderTextBlockStyle}" /> 

public string MyText { get; set; } 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    MyText = "new text!!"; 
    Bindings.Update(); 
} 

TextBlock新しいテキストが移入されます!。ここではデフォルトのOneTimeバインディング(つまり{x:Bind MyText})を使用し、MyTextは通常のCLRプロパティに過ぎません。

これは、最終的にBindings.Update()と呼ばれ、OneTimeバインディングを強制的に再初期化するためにのみ機能します。しかし

、私が先に言ったように、あなただけのUI まれニーズを更新する時には、上記のアプローチを使用してご検討ください。ほとんどの場合、これは当てはまりませんので、Bindings.Update()をまったく使用する必要はなく、INPCを実装し、OneWayバインディングを書きます。

関連する問題