0

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));
        }
    }
acmesoft
  • 9
  • 3

2 Answers2

0

Your models objects need to implement INotifyPropertyChanged in order to notify changes to the UI.

Leo M
  • 123
  • 1
  • 9
  • sorry, I updated the Ask, because I have an Implementation of INotifyPropertyChanged. – acmesoft Feb 20 '22 at 21:27
  • 1
    Implementation of INPC (INotifyPropertyChanged) on BaseViewmodel isn't enought. You also need to implement it on UserInfo & AdditionalInfo. – Leo M Feb 20 '22 at 22:09
0

You object is not notified that it changed. To solve your problem you can create a root class that inherits from InofifyPropertyChange .

public class Root : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        internal void RaisePropertyChanged([CallerMemberName]string propertyName ="")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        }

    }

then inherit any model from this class to implement Property Changed Event.

internal class AdditionalInfo : Root
{
  public string Address { get; set; }
  private string availability;
  
  public string Availability
  { 
  get{ return availability;}
  set
     { availability= value;  
       RaisePropertyChanged();
     } 
  }
}
Amjad S.
  • 1,196
  • 1
  • 4
  • 16
  • sorry, I updated the Ask, because I have an Implementation of INotifyPropertyChanged. – acmesoft Feb 20 '22 at 21:27
  • Mister @acmesoft , you need to implement it on the class AdditionalInfo. So please Try doing what i did in my solution. – Amjad S. Feb 20 '22 at 22:15
  • Sorry I didn’t see that your are also modifying LAstUPdate in the class USerInfo . Please Implement it on both classes USerInfo and additionalInfo – Amjad S. Feb 20 '22 at 22:17