【发布时间】:2017-11-19 15:05:42
【问题描述】:
在我的 UWP 应用中,我正在根据 API 调用返回的数据更新我的 UI。
MyPage 是我显示从 API 调用返回的数据的页面,我就是这样做的:
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;
}
}
这是我的观点:
<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 并添加这样的等待时:
_result = await new DocumentDetailsApiCall(_documentId).GetResponseAsync();
然后,我的 UI 只是不显示绑定值,它保持空白。我可以确认 viewModel 属性确实得到了更新。
我没有在我的 ViewModel 属性上实现INotifyPropertyChanged(我尝试实现它,没有改变任何东西)
更新按照建议,我已将 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 仍然有效。
【问题讨论】:
-
除非你有 INPC,否则它绝对不会工作;也许您的实施不正确?还; x:Bind 是怎么回事?
-
1) 视图模型应该实现
INotifyPropertyChanged来更新视图。这就是拥有它们的全部目的。 2) 移除阻塞调用.Result3) 确保视图中使用的属性名称与视图模型属性名称匹配。即volumeNumber,除非那是一个错字。 -
如果没有一个好的minimal reproducible example 可靠地重现问题,就不可能提供实际的答案。但请注意
{x:Bind}的默认模式是OneTime。您在绑定的Text属性上正确设置了OneWay,但不是Visibility属性。因此,一旦设置了初始绑定值,对属性值的更改就不会影响可见性。 -
因为在没有 INotifyProperryChanged 的情况下使用 .Result 而不是 await 可以完美工作,我认为没关系(该方法也是第一个也是唯一一个将值分配给 viewmodel 的地方)。我将做出建议的更改并更新我的答案。
-
尝试拨打
Bindings.Update()?
标签: c# uwp async-await