异步方法不是在第一次加载时绑定数据,而是在 UWP 中的第二次加载时绑定数据
本文关键字:数据 加载 绑定 第二次 UWP 异步方法 第一次 | 更新日期: 2023-09-27 18:32:39
我有一个异步方法。我正在尝试从网络上的 json 文件绑定列表视图。我正在开发一个通用的Windows平台应用程序。当我第二次打开页面时,正在加载列表视图。但是当然,我希望在第一次加载时加载列表视图。什么会导致问题?谢谢。这是我的 XAML 的代码隐藏。
public MyPage()
{
this.InitializeComponent();
Namedays = new List<NamedayModel>();
LoadData();
listview1.ItemsSource = Namedays;
}
public async void LoadData()
{
Namedays = await GetAllNamedaysAsync();
}
private static List<NamedayModel> allNamedaysCache;
public static async Task<List<NamedayModel>> GetAllNamedaysAsync()
{
if (allNamedaysCache != null)
return allNamedaysCache;
var client = new HttpClient();
var stream = await client.GetStreamAsync("http://www.example.com/myfile.json");
var serializer = new DataContractJsonSerializer(typeof(List<NamedayModel>));
allNamedaysCache = (List<NamedayModel>)serializer.ReadObject(stream);
return allNamedaysCache;
}
你做错了几件事:
- 如果不是真的需要(例如事件(,请不要使异步无效,
- 你在构造函数中运行你的
LoadData()
作为 fire-forget,它不会等待(在构造函数中也是不可能的(,代码更进一步,你将 listview 的 itemssource 设置为 Namedays。您没有对 ItemsSource 使用绑定,因此当您在加载的方法中更改 Namedays 时,列表视图不会反映它。 - 除此之外,通过为
LoadData()
中的 Namedays 分配新值,您不会更改 ListView 的 itemsSource 的值 - 它仍然指向旧集合。
在这种情况下,如果您对 ItemsSource 使用绑定,定义属性并在例如 Loaded 事件中异步加载数据,那就更好了。示例代码,XAML:
<ListView ItemsSource="{Binding Namedays}"/>
以及背后的代码:
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
private List<NamedayModel> namedays = new List<NamedayModel>();
public List<NamedayModel> Namedays { get { return namedays; } set { namedays = value; RaiseProperty(nameof(Namedays)); } }
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
this.Loaded += MainPage_Loaded;
}
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Namedays = await GetAllNamedaysAsync();
}
public static async Task<List<NamedayModel>> GetAllNamedaysAsync()
{
if (allNamedaysCache != null)
return allNamedaysCache;
var client = new HttpClient();
var stream = await client.GetStreamAsync("http://www.tyosoft.com/namedays_hu.json");
var serializer = new DataContractJsonSerializer(typeof(List<NamedayModel>));
allNamedaysCache = (List<NamedayModel>)serializer.ReadObject(stream);
return allNamedaysCache;
}
}
作为旁注 - 如果您想在不重新分配的情况下修改它,您也可以考虑使用 ObservableCollection 而不是 List。
您的listview1
不知道数据,因此不会加载它们。当您第二次打开页面时,数据已加载,listview1
可以显示它们。
您需要实现INotifyPropertyChanged
这样的接口:
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
然后在加载数据后调用OnPropertyChanged(nameof(Namedays))