2017-06-16 54 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; 
    } 
} 

这是使HTTP-POST请求API类:

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; 
     } 
    } 

这是我的观点:

<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> 

这工作,除了它完美块罚款UI,所以当我从方法调用中删除Result和添加的await李ke这:

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

然后,我的UI只是不显示绑定值,它仍然是空白。我可以确认viewModel属性确实得到更新。

我没有实现我的ViewModel属性INotifyPropertyChanged(我想实现它,并没有改变点儿)

UPDATE至于建议,我已经加入INPC我的ViewModel和我的继承人ViewModel类

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)确保视图中使用的属性名称与视图模型属性名称匹配。即'volumeNumber',除非这是一个错字。 – Nkosi

+3

如果没有好的[mcve]可靠地重现问题,就不可能提供实际的答案。但请注意,“{x:Bind}”的默认模式是“OneTime”。您已经在绑定的“文本”属性上正确设置了“OneWay”,但未设置“可见性”属性。因此,一旦设置了初始边界值,对属性值的更改将不会影响可见性。 –

回答

3

由于调用Bindings.Update()解决了您的问题,您的绑定表达式应该是正确的,但某种方式属性更改通知失败。

我不会猜测这里真的出了什么问题,而是要解释何时应该使用Bindings.Update(),以及何时应该使用INPC + OneWay绑定。

Bindings.Update()仅适用于x:Bind,不像传统的结合,如果你的UI很少需要用新的数据更新,您不必执行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 很少需要更新。大多数情况并非如此,因此您仍然会执行INPC并编写OneWay绑定,而根本不需要使用Bindings.Update()