Search code examples
c#sqlitexamarinxamarin.formsvisual-studio-mac

how to change change ui with async in xamarin forms


I try to develop a mobile app in xamarin forms. I have news list and i am using SQLite for store that. When my main page open, before i get the news from SQLite and then i try to get new news from web API. I can save the new news in SQLite but my UI hasn't changed. How can i fix that?

    public MainPage()
    {
        InitializeComponent();

        database = new Helper.xxxDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "xxx.db3"));

        SetLocalDBMainNews();

        Task.Run(async () => { await GetNewsAsync(); });
    }
    void SetLocalDBMainNews()
    {
        if(database.TableExists("News"))
        {
            List<News> newsList = database.GetNewsData();
            if (newsList.Count > 0)
            {
                MaiNewsList.ItemsSource = newsList.Where(x => x.Type.Equals((int)NewsType.MainNews)).OrderBy(x => x.Sort).ToList();
            }
        }
        else
            database.CreateNewsTable();
    }
    private async Task GetNewsAsync()
    {
        try
        {
            var register = database.GetRegisterData();
            string url = "http://xxx.azurewebsites.net/api/News/GetPublishedNews";
            var response = Tools.Send(url, "GET", register.Token);
            var result = JsonConvert.DeserializeObject<ApiResponse<List<News>>>(response);
            if (result.HasError == false)
            {
                var newsList = result.Value;
                database.DeleteAllNews();
                foreach(var n in newsList)
                {
                    database.Insert(n);
                }

                MaiNewsList.ItemsSource = newsList.Where(x => x.Type.Equals((int)NewsType.MainNews)).OrderBy(x => x.Sort).ToList();
            }
        }
        catch{}
    }

The code works for saving new news to SQLite but i couldn't bind the news to UI in async.

Edit :

After jason's answer, here is the my code latest version Device.BeginInvokeOnMainThread solve the my problem.

private async Task GetNewsAsync()
{
    try
    {
        var register = database.GetRegisterData();
        string url = "http://xxx.azurewebsites.net/api/News/GetPublishedNews";
        var response = Tools.Send(url, "GET", register.Token);
        var result = JsonConvert.DeserializeObject<ApiResponse<List<News>>>(response);
        if (result.HasError == false)
        {
            var newsList = result.Value;
            database.DeleteAllNews();
            foreach(var n in newsList)
            {
                database.Insert(n);
            }

            Device.BeginInvokeOnMainThread(() =>
            {
                MaiNewsList.ItemsSource = newsList.Where(x => x.Type.Equals((int)NewsType.MainNews)).OrderBy(x => x.Sort).ToList();
            });
        }
    }
    catch
    {

    }
}

Solution

  • UI changes need to happen on the UI thread using BeginInvokeOnMainThread

    Device.BeginInvokeOnMainThread( () =>
    {
        MaiNewsList.ItemsSource = newsList.Where(x => x.Type.Equals((int)NewsType.MainNews)).OrderBy(x => x.Sort).ToList();
    });