I have managed to get it working, the solution was a combination of using async-await and moving the population code to OnAppearing()
Xamarin Forms CollectionView not showing dat
I have tried so many different things and looked at so many different examples, tutorials, forum posts - but I just can't get this to work. Note: I am new to Xamarin so some of this may not be ideal / the best way of doing things!
I have a page that needs to display a list of items (devices). I am using CollectionView:
DevicesPage.xaml contains:
<ContentPage.BindingContext>
<viewModels:DevicesPageViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Label Text="My Devices"/>
<CollectionView x:Name="DevicesView" ItemsSource="{Binding MyDevices}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ProductImage}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Row="0" Grid.Column="1"
Text="{Binding MaskedPAN, StringFormat='PAN: {0}'}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1" HeightRequest="30"
Text="{Binding CardBalanceText}"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage.Content>
DevicesPage.xaml.cs contains:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DevicesPage : ContentPage
{
public DevicesPage()
{
InitializeComponent();
//BindingContext = new DevicesPageViewModel();
}
}
DevicesPageViewModel.cs contains:
public class DevicesPageViewModel : BaseViewModel
{
public ObservableCollection<MyDevice> MyDevices { get; set; }
public DevicesPageViewModel()
{
var api = new apiService(Configuration.ApiBaseUrl);
var rtnData = api.GetUserDevices(CredentialsStorage.GetAccessTokenAsync().Result);
MyDevices = new ObservableCollection<MyDevice>();
foreach (var device in rtnData.Data.Devices)
{
var newDevice = new MyDevice
{
ProductId = device.ProductId,
CurrencyCode = device.CurrencyCode,
IsLive = device.IsLive,
MaskedPAN = device.MaskedPAN,
Primary = device.Primary,
PrimaryToken = device.PrimaryToken,
Product = device.Product,
PublicToken = device.PublicToken,
StatCode = device.StatCode,
UserDefinedName = device.UserDefinedName,
ProductImage = ImageSource.FromResource(device.ProductImage)
};
MyDevices.Add(newDevice);
}
}
}
MyDevice.cs contains:
public class MyDevice
{
public string ProductId { get; set; }
public string CurrencyCode { get; set; }
public string StatCode { get; set; }
public string PublicToken { get; set; }
public string Primary { get; set; }
public string PrimaryToken { get; set; }
public string IsLive { get; set; }
public string Product { get; set; }
public string MaskedPAN { get; set; }
public string UserDefinedName { get; set; }
public ImageSource ProductImage { get; set; }
public string CardBalance { get; set; }
public string CardBalanceText
{
get
{
if (CardBalance != null && !string.IsNullOrEmpty(CardBalance))
{
return $"Balance: £{CardBalance:F2}";
}
return string.Empty;
}
}
}
And this is what I get when I run the app in the Android emulator:
So - why do none of the values show?!
I have debugged it and the list of devices is definitely being populated.
Developer technologies | .NET | Xamarin
1 additional answer
Sort by: Most helpful
-
JarvanZhang 23,971 Reputation points
2021-03-10T02:00:36.807+00:00 Hello,
Welcome to our Microsoft Q&A platform!
The number of (blank) rows is correct, but no content is showing!? It’s like the binding of each element isn’t working
Hi, GordonS-9701. I created a basic demo to test the function and replace the populating data code as below, it works fine. There may be something wrong with the part of populating data, please mark sure the data have been added successfully. Try adding a breakpoint to check the 'MyDevices' collection. You could use the following code to test to vertify the function.
public DevicesPageViewModel() { //var api = new apiService(Configuration.ApiBaseUrl); //var rtnData = api.GetUserDevices(CredentialsStorage.GetAccessTokenAsync().Result); MyDevices = new ObservableCollection<MyDevice>(); for (int i = 0; i < 10; i++) { var newDevice = new MyDevice { ProductId = "ProductId_" + i, CurrencyCode = "CurrencyCode_" + i, IsLive = "IsLive_" + i, MaskedPAN = "MaskedPAN_" + i, Primary = "Primary_" + i, PrimaryToken = "PrimaryToken" + i, Product = "Product" + i, PublicToken = "PublicToken" + i, StatCode = "StatCode" + i, UserDefinedName = "UserDefinedName" + i, ProductImage = "grid_" }; MyDevices.Add(newDevice); } }The
CredentialsStorage.GetAccessTokenAsync()command may take some time to get the result, try to useasync-awaitwrap the code to ensure to get the correct result.Best Regards,
Jarvan Zhang
If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.