I'm on the stable channel using Xamarin.Forms 1.2.3.6257 focusing on Android. I'm relatively new to XAML, Xamarin, and the async/await pattern.
The code below is querying a web service to populate a ListView. The web service sometimes takes 5 seconds to return data so I want to display a HUD (AndHUD) message while the query is running. The HUD stuff seems to be working ok. When the app starts up the only <ContentPage Title="{Binding Title}">
appears to be bound. The ListView is empty. That tells me the web service returned data but for some reason only part of the XAML gets bound. When I click the Refresh tool bar item the ListView gets populated correctly with the HUD working as expected.
I'm populating things in OnAppearing
to avoid dealing with async/await issues in the constructor.
I have less than two dozen items in each of the tab pages so things like scrolling performance aren't an issue for me now. I tried setting BindingContext in a few places in addition to ItemsSource but that didn't seem to make any difference.
What am I doing wrong to cause the ListView to not populate during the initial load?
<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Company.XamarinForms.Welcome"
Title="Welcome"
Appearing="OnAppearing">
<!-- http://codeworks.it/blog/?p=232 -->
<TabbedPage.ToolbarItems>
<!-- http://forums.xamarin.com/discussion/19225/icon-image-on-toolbar-item-in-xamarin-forms -->
<ToolbarItem Name="Search" Activated="OnToolBarItemActivated" Order="Primary" Priority="0" Icon="ic_action_search.png" />
<ToolbarItem Name="Refresh" Activated="OnToolBarItemActivated" Order="Primary" Priority="1" Icon="ic_action_refresh.png" />
<ToolbarItem Name="Logout" Activated="OnToolBarItemActivated" Order="Secondary" Priority="2" />
<ToolbarItem Name="About" Activated="OnToolBarItemActivated" Order="Secondary" Priority="3" />
</TabbedPage.ToolbarItems>
<TabbedPage.ItemTemplate>
<DataTemplate>
<ContentPage Title="{Binding Title}">
<!--- http://blog.falafel.com/learning-xamarin-forms-and-xaml/ -->
<ListView ItemsSource="{Binding Claims}" ItemTapped="OnListViewItemTapped">
<ListView.ItemTemplate>
<!-- http://forums.xamarin.com/discussion/25581/how-to-use-a-datatemplate-in-a-listview-in-xaml -->
<DataTemplate>
<ViewCell>
<!-- http://motzcod.es/post/94643411707/enhancing-xamarin-forms-listview-with-grouping-headers -->
<StackLayout VerticalOptions="FillAndExpand" Padding="10">
<Label Text="{Binding ClaimNumber}" Font="Large" VerticalOptions="Center" HorizontalOptions="FillAndExpand" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
</DataTemplate>
</TabbedPage.ItemTemplate>
</TabbedPage>
`
// http://forums.xamarin.com/discussion/17388/tabbedpage
public partial class Welcome : TabbedPage
{
public bool _firstAppearance = true;
public Welcome ()
{
InitializeComponent ();
}
// https://github.com/xamarin/xamarin-forms-samples/blob/master/Todo/SharedProject/Todo/Views/TodoListPage.cs#L101
public async void OnAppearing(object sender, EventArgs e)
{
// HACK: prevent a refresh from occurring when the child page is popped away
if (_firstAppearance)
{
await SetItemsSourceWithHud();
_firstAppearance = false;
}
}
public async void OnListViewItemTapped(object sender, ItemTappedEventArgs e)
{
ClaimData.Claim claim = (ClaimData.Claim)e.Item;
await Navigation.PushAsync(new Detail(claim));
((ListView)sender).SelectedItem = null;
}
public async void OnToolBarItemActivated(object sender, EventArgs e)
{
ToolbarItem item = (ToolbarItem) sender;
if (item.Name == "Refresh")
{
await SetItemsSourceWithHud();
}
else
{
await DisplayAlert("Coming soon...", item.Name,"OK");
}
}
private async Task SetItemsSourceWithHud()
{
var hud = DependencyService.Get<IHud> (); // AndHUD
hud.Show ("Refreshing...");
var result = await App.GetClaimData ();
ItemsSource = result.Summaries;
hud.Dismiss ();
}
}
`
`
public class ClaimData
{
public List Summaries { get; set; }
public class ClaimSummary
{
public string Title { get; set; }
public List<Claim> Claims { get; set; }
public ClaimSummary (string title)
{
this.Title = title;
}
}
public class Claim
{
public string ClaimNumber { get; set; }
}
}
`
The forum doesn't seem to like my code
formatting either...weird.