I want to make cards with Name and Details.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MinerController.ViewModels"
xmlns:cards="clr-namespace:Syncfusion.XForms.Cards;assembly=Syncfusion.Cards.XForms"
x:Class="MinerController.Views.Dashboard"
Appearing="ContentPage_Appearing">
<ContentPage.BindingContext>
<vm:DashboardVM />
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Label Text="Datos de las pools" FontSize="Title" HorizontalTextAlignment="Center" />
<StackLayout BindableLayout.ItemsSource="{Binding UserInfo}" BindableLayout.EmptyView="No data." Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<cards:SfCardView BackgroundColor="SlateGray" HasShadow="True" WidthRequest="100" Margin="5" Padding="5">
<Grid>
<Label Grid.Row="0" Text="{Binding Name}"/>
<Label Grid.Row="1" Text="{Binding LastUpdateHumanized}" />
<StackLayout Grid.Row="2" BindableLayout.ItemsSource="{Binding AdditionalInfo}" BindableLayout.EmptyView="No data.">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid>
<Label Grid.Row="0" Text="{Binding Address}" />
<Label Grid.Row="1" Text="{Binding Availability}" />
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Grid>
</cards:SfCardView>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
ViewModel:
internal class DashboardVM : BaseViewModel
{
private InternalService internalService;
public ObservableCollection<UserInfo> UserInfo { get; private set; }
public DashboardVM()
{
UserInfo = new ObservableCollection<UserInfo>();
internalService = new InternalService();
if (ConfigService.Configuration != null)
{
foreach(var person in ConfigService.Configuration.Persons)
{
UserInfo.Add(new UserInfo() { Name = person.Name, AdditionalsInfo = new ObservableCollection<AdditionalInfo>() });
foreach(var additionalinfo in person.AdditionalsInfo)
{
UserInfo.Last().AdditionalsInfo.Add(new AdditionalInfo() { address = person.Address, Availiability = person.Availability });
}
}
_ = TimedUpdate();
}
}
private async Task TimedUpdate()
{
while (true)
{
await UpdateInfo();
await Task.Delay(60000);
}
}
public async Task UpdateInfo()
{
foreach (var user in UserInfo)
{
foreach (var additionalInfo in user.AdditionalsInfo)
{
additionalInfo.Availability = await internalservice.GetAvailability(user.Name, additionalInfo.Address);
}
user.LastUpdate = DateTime.Now;
}
OnPropertyChanged(nameof(UserInfo));
}
}
Models:
internal class UserInfo
{
public string Name { get; set; }
public ObservableCollection<AdditionalInfo> AdditionalsInfo { get; set; }
public DateTime LastUpdate { get; set; }
public string LastUpdateHumanized { get { return LastUpdate.Humanize(); } }
}
internal class AdditionalInfo
{
public string Address { get; set; }
public string Availability { get; set; }
}
The result of this code is the following: when the first time I load, it get all data from config file, then, periodically I need to update "availability" of the user, but when I update the object, it doesn't update on screen. Maybe binding is ignored, but why?, or the issue is because of nested object? I'm doing well? Before helping me, please read the follow: I don't want a workaround because I still need populating the "dashboard" with another things, and making something outside mvvm, I believe is ugly.
Thank you!
Edit: Sorry I forgot show the BaseViewModel:
internal class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}