Listview with information of 2 or more ObservableCollections

Enrique4toEnrique4to Member ✭✭

Hello:

I Have a ListView in a ContentPage, and 2 ObservableCollections in a ViewModel.

What I want is in the Lisetview, list information from both ObservableCollections.

                        <ListView                    
                            HasUnevenRows="True"
                            IsPullToRefreshEnabled="True"
                            IsRefreshing="{Binding IsRefreshing}"                    
                            ItemsSource="{Binding Jobs}"
                            RefreshCommand="{Binding RefreshJubssCommand}">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <ViewCell>
                                        <Grid>
                                            <!--<Grid.GestureRecognizers>
                                                <TapGestureRecognizer Command="{Binding JobPageCommand}"/>
                                            </Grid.GestureRecognizers>-->
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="Auto"/>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width=".05*"/>
                                            </Grid.ColumnDefinitions>
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto"/>
                                            </Grid.RowDefinitions>

                                            <StackLayout
                                                Grid.Column="1"
                                                HorizontalOptions="StartAndExpand"
                                                VerticalOptions="CenterAndExpand">
                                                <Label
                                                    FontAttributes="Bold"
                                                    FontSize="14"
                                                    Text="{Binding Subject}" **<--ObservableCollection Jobs**
                                                    TextColor="LightGray"
                                                    VerticalTextAlignment="End"/>
                                                <StackLayout
                                                    HorizontalOptions="StartAndExpand"
                                                    Orientation="Horizontal"
                                                    VerticalOptions="Start">
                                                    <Label
                                                        FontAttributes="Bold"
                                                        FontSize="12"
                                                        HorizontalOptions="Start"
                                                        Text="{Binding Date_Start}" **<--ObservableCollection Dates**
                                                        TextColor="LightGray"
                                                        VerticalTextAlignment="Start"/>
                                                    <Label
                                                        FontAttributes="Bold"
                                                        FontSize="12"
                                                        HorizontalOptions="StartAndExpand"
                                                        Text="{Binding Hour_Start}" **<--ObservableCollection Dates**
                                                        TextColor="LightGray"
                                                        VerticalTextAlignment="Start"/>
                                                </StackLayout>
                                            </StackLayout>
                                            <Image
                                                Grid.Column="2"
                                                HorizontalOptions="StartAndExpand"
                                                Source="ChevronRight"
                                                VerticalOptions="Center"
                                                WidthRequest="20"/>
                                        </Grid>
                                    </ViewCell>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>

How can I do that

Best Answers

  • Enrique4toEnrique4to ✭✭
    Accepted Answer

    Done
    This is the code

    Models:

    User Model

        public class T_users
        {
            #region Properties
            [Key]
            public int Id_user { get; set; }
            [Required]
            public string User { get; set; }
            [Required]
            public string Pass { get; set; }
            public byte[] Profile_Picture { get; set; }
            #endregion
        }
    

    Customer Model

        public class T_customers
        {
            #region Properties
            [Key]
            public int Id_Customer { get; set; }
            [Required]
            public string Name{ get; set; }
            [Required]
            public string LastName { get; set; }
            [Required]
            public string Mail { get; set; }
            [Required]
            public string Phone { get; set; }
            [Required]
            public int Id_User { get; set; }
            #endregion
        }
    

    CustomerCollection Model

            public class CustomerCollection
            {
                #region Properties
                public int Id_Customer { get; set; }
                public string Name{ get; set; }
                public string LastName { get; set; }
                public string Mail { get; set; }
                public string Phone { get; set; }
                public int Id_User { get; set; }
    
    
                public byte[] Profile_Picture { get; set; }
    
    
                #endregion
            }
    

    I only add the Profile_Picture from T_users, to T_customers in CustomerCollection Model

    I Made a CustomerItemViewModel to get the Customer later, in dependency to CustomerCollection instead T_customers like this...

        public class CustomerItemViewModel : CustomerCollection
        { 
            #region Services
            private ApiService apiService;
            #endregion
    
            #region Attributes
            public ClientesCollection customer;
            public T_users user;
            #endregion
    
            #region Properties
            #endregion
    
            #region Constructors
            public CustomerItemViewModel()
            {
                this.apiService = new ApiService();
            }
            #endregion
    
            #region Commands
            public ICommand CustomerPageCommand
            {
                get
                {
                    return new RelayCommand(GoToCustomerPage);
                }
            }
            #endregion
    
            #region Methods
            private async void GoToEmpresaPage()
            {
                this.user = MainViewModel.GetInstance().UserHome.user;
                MainViewModel.GetInstance().Customer = new CustomerViewModel(this, user );
                await Application.Current.MainPage.Navigation.PushModalAsync(new CustomerPage());
            }
            #endregion
        }
    

    And, in My ViewModel this is how I get the information that I Want... From two Lists... One that I get before in other View model cals ListUser, and the ListCustomer that I get on this code...

            private async void LoadCustomer()
            {
                this.IsRefreshing = true;
                this.IsRunning = true;
    
                var connection = await this.apiService.CheckConnection();
                if (!connection.IsSuccess)
                {
                    this.IsRunning = false;
                    this.IsRefreshing = false;
                    await Application.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        connection.Message,
                        "OK");
                    return;
    
                }
    
                var urlApi = Application.Current.Resources["UrlAPI"].ToString();
                var prefix = Application.Current.Resources["UrlPrefix"].ToString();
                var controller = Application.Current.Resources["UrlT_customersController"].ToString();
    
                var response = await this.apiService.GetList<T_customers>(urlApi, prefix, controller);
    
                if (!response.IsSuccess)
                {
                    this.IsRunning = false;
                    this.IsRefreshing = false;
                    await Application.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        response.Message,
                        "OK");
                    return;
                }
    
                this.CustomerList = (List<T_customers>)response.Result;
                this.RefreshCustomerList();
    
                this.IsRefreshing = false;
                this.IsRunning = false;
    
            }
            public void RefreshCustomerList()
            {
                var userList = MainViewModel.GetInstance().Login.ListUsers;
                    var customerSelected = this.CustomerList.Select(e => new CustomerItemViewModel
                    {
                        LastName= e.LastName,
                        Id_Customer = e.Id_Customer,
                        Name= e.Name,
                        Id_User = e.Id_User,
                        Mail= e.Mail,
                        Phone = e.Phone ,
    
                        Profile_Picture = userList.FirstOrDefault(u => u.Id_User  == e.Id_User ).Profile_Picture
    
                    });
    
                    this.Customers = new ObservableCollection<CustomerItemViewModel>(
                    customerSelected.OrderBy(e => e.Name));
            }
    

    On RefreshCustomerList() method, the Profile_Picture is obtained from a validation.

    And this is How I have my Xaml Page

                            <ListView                    
                                HasUnevenRows="True"
                                IsPullToRefreshEnabled="True"
                                IsRefreshing="{Binding IsRefreshing}"                    
                                ItemsSource="{Binding Customers}"
                                RefreshCommand="{Binding RefreshCustomerCommand}">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
                                            <Grid>
                                                <!--<Grid.GestureRecognizers>
                                                    <TapGestureRecognizer Command="{Binding CustomerPageCommand}"/>
                                                </Grid.GestureRecognizers>-->
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width=".05*"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto"/>
                                                </Grid.RowDefinitions>
    
                                                <StackLayout
                                                    Grid.Column="1"
                                                    HorizontalOptions="StartAndExpand"
                                                    VerticalOptions="CenterAndExpand">
                                                    <Label
                                                        FontAttributes="Bold"
                                                        FontSize="14"
    
                                                        Text="{Binding Name}"      <--Here is the Customer Detail.
    
                                                        TextColor="LightGray"
                                                        VerticalTextAlignment="End"/>
                                                    <StackLayout
                                                        HorizontalOptions="StartAndExpand"
                                                        Orientation="Horizontal"
                                                        VerticalOptions="Start">
                                                        <Label
                                                            FontAttributes="Bold"
                                                            FontSize="12"
                                                            HorizontalOptions="Start"
    
                                                            Text="{Binding LastName}"   <--Here is the Customer Detail.
    
                                                            TextColor="LightGray"
                                                            VerticalTextAlignment="Start"/>
                                                        <Label
                                                            FontAttributes="Bold"
                                                            FontSize="12"
                                                            HorizontalOptions="StartAndExpand"
    
                                                            Text="{Binding Phone}"  <--Here is the Customer Detail.
    
                                                            TextColor="LightGray"
                                                            VerticalTextAlignment="Start"/>
                                                    </StackLayout>
                                                </StackLayout>
                                                <Image
                                                    Grid.Column="2"
                                                    HorizontalOptions="StartAndExpand"
    
                                                    Source="{Binding Profile_Picture}"       <--Here is the User Detail.
    
                                                    VerticalOptions="Center"
                                                    WidthRequest="20"/>
                                            </Grid>
                                        </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
    

    I Hope it helps to any One whith this.

    Thanks for all your help... @voidstream And @yelinzh , you really help me to get the Solution....

Answers

  • JamesLaveryJamesLavery GBBeta, University ✭✭✭✭✭
    You will need to combine the two collections into one and bind to that.
  • Enrique4toEnrique4to Member ✭✭
    > @JamesLavery said:
    > You will need to combine the two collections into one and bind to that.

    I'm Sorry, I'm kind of new on this, can you show me how to do that, 'couse I'm try observablecollection.Union, but it doesn't works....
  • JamesLaveryJamesLavery GBBeta, University ✭✭✭✭✭
    Please post your viewmodel/pagemodel code where you are retrieving/populating your observable collections.
  • voidstreamvoidstream FRMember ✭✭✭
    edited April 16

    @Enrique4to said:
    > @JamesLavery said:
    > You will need to combine the two collections into one and bind to that.

    I'm Sorry, I'm kind of new on this, can you show me how to do that, 'couse I'm try observablecollection.Union, but it doesn't works....

    If you just use Add/Remove from the ObservableCollection you don't need to Notify your view, but if you write "your Collection = anything" you should implement INotifyPropertyChanged. Don't forget this, this rules is for all properties binded :smile:

    public class MyViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        private ObservableCollection<object> _myCollection;
        public ObservableCollection<object> MyCollection
        {
            get => _myCollection
            set => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyCollection)));
        }       
    }
    

    You can use a Framework (like PRISM) for easier implementation and for others features

  • Enrique4toEnrique4to Member ✭✭

    @JamesLavery said:
    Please post your viewmodel/pagemodel code where you are retrieving/populating your observable collections.

    Shure:

    Page:

                            <ListView                    
                                HasUnevenRows="True"
                                IsPullToRefreshEnabled="True"
                                IsRefreshing="{Binding IsRefreshing}"                    
                                ItemsSource="{Binding Jobs}"
                                RefreshCommand="{Binding RefreshJubssCommand}">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
                                            <Grid>
                                                <!--<Grid.GestureRecognizers>
                                                    <TapGestureRecognizer Command="{Binding JobPageCommand}"/>
                                                </Grid.GestureRecognizers>-->
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width=".05*"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto"/>
                                                </Grid.RowDefinitions>
    
                                                <StackLayout
                                                    Grid.Column="1"
                                                    HorizontalOptions="StartAndExpand"
                                                    VerticalOptions="CenterAndExpand">
                                                    <Label
                                                        FontAttributes="Bold"
                                                        FontSize="14"
                                                        Text="{Binding Subject}" **<--ObservableCollection Jobs**
                                                        TextColor="LightGray"
                                                        VerticalTextAlignment="End"/>
                                                    <StackLayout
                                                        HorizontalOptions="StartAndExpand"
                                                        Orientation="Horizontal"
                                                        VerticalOptions="Start">
                                                        <Label
                                                            FontAttributes="Bold"
                                                            FontSize="12"
                                                            HorizontalOptions="Start"
                                                            Text="{Binding Date_Start}" **<--ObservableCollection Dates**
                                                            TextColor="LightGray"
                                                            VerticalTextAlignment="Start"/>
                                                        <Label
                                                            FontAttributes="Bold"
                                                            FontSize="12"
                                                            HorizontalOptions="StartAndExpand"
                                                            Text="{Binding Hour_Start}" **<--ObservableCollection Dates**
                                                            TextColor="LightGray"
                                                            VerticalTextAlignment="Start"/>
                                                    </StackLayout>
                                                </StackLayout>
                                                <Image
                                                    Grid.Column="2"
                                                    HorizontalOptions="StartAndExpand"
                                                    Source="ChevronRight"
                                                    VerticalOptions="Center"
                                                    WidthRequest="20"/>
                                            </Grid>
                                        </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
    

    ViewModel:

        public class UserHomeViewModel : BaseViewModel
        {
            #region Services
            private ApiService apiService;
            #endregion
    
            #region Attributes
    
            private ObservableCollection<DatesItemViewModel>dates;
            private ObservableCollection<JobsItemViewModel> Jobs;
    
            private T_trabajos trabajo;
            private T_trabajocitas cita;
    
            #endregion
    
            #region Properties
    
            public List<T_jobs> JobsList { get; set; }
            public List<T_jobdates> CitasList { get; set; }
    
            public T_trabajos Job
            {
                get { return this.job; }
                set { SetValue(ref this.job, value); }
            }
            public T_trabajocitas Date
            {
                get { return this.date; }
                set { SetValue(ref this.date, value); }
            }
    
            public ObservableCollection<T_trabajos> Trabajos
            {
                get { return this.trabajos; }
                set { SetValue(ref this.trabajos, value); }
            }
            public ObservableCollection<DatesItemViewModel> Dates
            {
                get { return this.citas; }
                set { this.citas = value; }
            }
    
            #endregion
    
            #region Constructors
            public UserHomeViewModel()
            {
                this.apiService = new ApiService();
                Task.Run(async () => { await this.LoadCitas(); }).Wait();
            }
    
            #endregion
    
            #region Commands
    
            public ICommand RefreshDatesCommand
            {
                get
                {                
                    return new RelayCommand(RefreshDatesList);
                }
            }
    
            #endregion
    
            #region Methods
    
            private async Task LoadDates()
            {
                this.IsRefreshing = true;
    
                var connection = await this.apiService.CheckConnection();
                if (!connection.IsSuccess)
                {
                    this.IsRefreshing = false;
                    await App.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        connection.Message,
                        "OK");
                    return;
    
                }
    
                var urlApi = App.Current.Resources["UrlAPI"].ToString();
                var prefix = App.Current.Resources["UrlPrefix"].ToString();
                var controller = App.Current.Resources["UrlT_jobsController"].ToString();
    
                var response = await this.apiService.GetList<T_Jobs>(urlApi, prefix, controller);
                if (!response.IsSuccess)
                {
                    this.IsRefreshing = true;
                    await App.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        response.Message,
                        "OK");
                    return;
                }
                var joblist = (List<T_Jobs>)response.Result;
                this.JobsList = joplist.Where(c => c.Id_Customer == this.customer.Id_Customer).ToList();
    
                var date = this.DatesList.Select(c => new DatesItemViewModel
                {
                    Id_Job = c.Id_Job,
                    Id_Customer = c.Id_Customer,
                    subject = c.subject,
                    Id_local = c.Id_local,
                    Strat_Price = c.Strat_Price,
                    Advance_Price = c.Advance_Price,
                });
    
                this.Dates = new ObservableCollection<DatesItemViewModel>(date.OrderBy(c => c.F_Start));
    
                controller = App.Current.Resources["UrlT_jobdatesController"].ToString();
    
                response = await this.apiService.GetList<T_JobDates>(urlApi, prefix, controller);
                if (!response.IsSuccess)
                {
                    this.IsRefreshing = true;
                    await App.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        response.Message,
                        "OK");
                    return;
                }
                var list = (List<T_JobDates>)response.Result;
                this.DatesList = list.Where(c => c.Id_Customer == this.customer.Id_Customer).ToList();
    
                var date = this.DatesList.Select(c => new DatesItemViewModel
                {
                    Id_Date = c.Id_Date,
                    Id_Job = c.Id_Job,
                    Id_Customer = c.Id_Customer,
                    Id_Artist = c.Id_Artist,
                    Date_Start = c.Date_Start,
                    Hour_Start = c.Hour_Start,
                    Date_End = c.Date_End,
                    Hour_End = c.Hour_End,
    
                });
    
                this.Dates = new ObservableCollection<DatesItemViewModel>(date.OrderBy(c => c.F_Start));
    
                this.IsRefreshing = false;
    
            }
            public void RefreshCitaList()
            {
                Task.Run(async () => { await this.LoadDates(); }).Wait();
            }
            #endregion
            }
    
            #endregion
    
        }
    

    As you can see, I'm using a web service with a Azure SQL Database connection, so the ObservableCollections only get data from the DataBase.

    I hope tha code helps to understand what I want...

    Thanks

  • Enrique4toEnrique4to Member ✭✭

    @yelinzh said:
    You can create a new Model class and put the two model in the class. Then you just need to create and bind one ObservableCollection.
    As following code shows:

    Model.cs

    namespace App6
    {
        public class Model_Collection
        {
            public Model_1 Model_1 { get; set; }
    
            public Model_2 Model_2 { get; set; }
    
        }
    
        public class Model_1 {
            public string Text { get; set; }
        }
    
        public class Model_2
        {
            public string Content { get; set; }
        }
    }
    

    page.xaml.cs

    public partial class Page4 : ContentPage
    {
        ObservableCollection<Model_Collection> list = new ObservableCollection<Model_Collection>();
        public Page4()
        {
            InitializeComponent();
    
            list.Add(new Model_Collection() { Model_1 = new Model_1 { Text = "text_1" }, Model_2 = new Model_2 { Content = "content_1" } });
            list.Add(new Model_Collection() { Model_1 = new Model_1 { Text = "text_2" }, Model_2 = new Model_2 { Content = "content_2" } });
            list.Add(new Model_Collection() { Model_1 = new Model_1 { Text = "text_3" }, Model_2 = new Model_2 { Content = "content_3" } });
    
            listview.ItemsSource = list;
        }
    }
    

    page.xaml

    <StackLayout>
        <Label Text="Two ObservableCollection Binding" />
        <ListView x:Name="listview">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Label x:Name="label1" Text="{Binding Model_1.Text}" HorizontalOptions="CenterAndExpand" Grid.Row="0" Grid.Column="0"/>
                            <Label x:Name="label" Text="{Binding Model_2.Content}" HorizontalOptions="CenterAndExpand" Grid.Row="1" Grid.Column="0"/>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
    

    It doesn't works for me... can you explain it with WebService connected to an Azure SQL DataBase?
    Thanks!!

  • Enrique4toEnrique4to Member ✭✭

    @voidstream said:

    @Enrique4to said:
    > @JamesLavery said:
    > You will need to combine the two collections into one and bind to that.

    I'm Sorry, I'm kind of new on this, can you show me how to do that, 'couse I'm try observablecollection.Union, but it doesn't works....

    If you just use Add/Remove from the ObservableCollection you don't need to Notify your view, but if you write "your Collection = anything" you should implement INotifyPropertyChanged. Don't forget this, this rules is for all properties binded :smile:

    public class MyViewModel : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection _myCollection;
    public ObservableCollection MyCollection
    {
    get => _myCollection
    set => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyCollection)));
    }
    }

    You can use a Framework (like PRISM) for easier implementation and for others features

    I'm already using this as BaseViewModel... Thanks.

  • voidstreamvoidstream FRMember ✭✭✭

    @Enrique4to said:

    @voidstream said:

    @Enrique4to said:
    > @JamesLavery said:
    > You will need to combine the two collections into one and bind to that.

    I'm Sorry, I'm kind of new on this, can you show me how to do that, 'couse I'm try observablecollection.Union, but it doesn't works....

    If you just use Add/Remove from the ObservableCollection you don't need to Notify your view, but if you write "your Collection = anything" you should implement INotifyPropertyChanged. Don't forget this, this rules is for all properties binded :smile:

    public class MyViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        private ObservableCollection<object> _myCollection;
        public ObservableCollection<object> MyCollection
        {
            get => _myCollection
            set => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyCollection)));
        }       
    }
    

    You can use a Framework (like PRISM) for easier implementation and for others features

    I'm already using this as BaseViewModel... Thanks.

    It's fixed? If not care about the current thread.

    You are calling Task.Run(), result you are leaving the main thread (UI Thread). You should use BeginInvokeOnMainThread when your code is firing the UI. For example

    Device.BeginInvokeOnMainThread(() =>
    {
        this.Dates = new ObservableCollection<DatesItemViewModel>(date.OrderBy(c => c.F_Start));
         this.IsRefreshing = false;
    }
    

    Don't use .Wait()
    Use configureAwait(false) if you don't need switch context

    More, watch this:
    https://docs.microsoft.com/en-US/dotnet/api/system.threading.cancellationtokensource?view=netframework-4.8
    https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=netframework-4.8

  • voidstreamvoidstream FRMember ✭✭✭
    @Enrique4to You should inject your ApiService by constructor to your viewmodel (Dependency injection vu constructor). Have fun 😊
  • Enrique4toEnrique4to Member ✭✭

    Hello, still not working...

    Maybe I'm not explain it well.

    I Have another Example on my code...

    I have the model Users

        public class T_users
        {
            #region Properties
            [Key]
            public int Id_user { get; set; }
            [Required]
            public string User { get; set; }
            [Required]
            public string Pass { get; set; }
            public byte[] Profile_Picture { get; set; }
            #endregion
        }
    

    And Customers Model

        public class T_customers
        {
            #region Properties
            [Key]
            public int Id_Customer { get; set; }
            [Required]
            public string Name{ get; set; }
            [Required]
            public string Lastname { get; set; }
            [Required]
            public string Mail { get; set; }
            [Required]
            public string Phone { get; set; }
            [Required]
            public int Id_User { get; set; }
            #endregion
        }
    

    I want to get the profile Image from Users Model Where Id_User is the same in the Customers Model Id_User and show the Image, Name And LastName in One ListView.

    How can I do that with an ObservableCollection in My ViewModel?

  • JamesLaveryJamesLavery GBBeta, University ✭✭✭✭✭
    You will have to create a separate class which exposes these two properties. You could have it containing the User and Customer classes and exposing the relevant properties.

    The bottom line is that you can only bind a listview to a single collection.
  • Enrique4toEnrique4to Member ✭✭
    Accepted Answer

    Done
    This is the code

    Models:

    User Model

        public class T_users
        {
            #region Properties
            [Key]
            public int Id_user { get; set; }
            [Required]
            public string User { get; set; }
            [Required]
            public string Pass { get; set; }
            public byte[] Profile_Picture { get; set; }
            #endregion
        }
    

    Customer Model

        public class T_customers
        {
            #region Properties
            [Key]
            public int Id_Customer { get; set; }
            [Required]
            public string Name{ get; set; }
            [Required]
            public string LastName { get; set; }
            [Required]
            public string Mail { get; set; }
            [Required]
            public string Phone { get; set; }
            [Required]
            public int Id_User { get; set; }
            #endregion
        }
    

    CustomerCollection Model

            public class CustomerCollection
            {
                #region Properties
                public int Id_Customer { get; set; }
                public string Name{ get; set; }
                public string LastName { get; set; }
                public string Mail { get; set; }
                public string Phone { get; set; }
                public int Id_User { get; set; }
    
    
                public byte[] Profile_Picture { get; set; }
    
    
                #endregion
            }
    

    I only add the Profile_Picture from T_users, to T_customers in CustomerCollection Model

    I Made a CustomerItemViewModel to get the Customer later, in dependency to CustomerCollection instead T_customers like this...

        public class CustomerItemViewModel : CustomerCollection
        { 
            #region Services
            private ApiService apiService;
            #endregion
    
            #region Attributes
            public ClientesCollection customer;
            public T_users user;
            #endregion
    
            #region Properties
            #endregion
    
            #region Constructors
            public CustomerItemViewModel()
            {
                this.apiService = new ApiService();
            }
            #endregion
    
            #region Commands
            public ICommand CustomerPageCommand
            {
                get
                {
                    return new RelayCommand(GoToCustomerPage);
                }
            }
            #endregion
    
            #region Methods
            private async void GoToEmpresaPage()
            {
                this.user = MainViewModel.GetInstance().UserHome.user;
                MainViewModel.GetInstance().Customer = new CustomerViewModel(this, user );
                await Application.Current.MainPage.Navigation.PushModalAsync(new CustomerPage());
            }
            #endregion
        }
    

    And, in My ViewModel this is how I get the information that I Want... From two Lists... One that I get before in other View model cals ListUser, and the ListCustomer that I get on this code...

            private async void LoadCustomer()
            {
                this.IsRefreshing = true;
                this.IsRunning = true;
    
                var connection = await this.apiService.CheckConnection();
                if (!connection.IsSuccess)
                {
                    this.IsRunning = false;
                    this.IsRefreshing = false;
                    await Application.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        connection.Message,
                        "OK");
                    return;
    
                }
    
                var urlApi = Application.Current.Resources["UrlAPI"].ToString();
                var prefix = Application.Current.Resources["UrlPrefix"].ToString();
                var controller = Application.Current.Resources["UrlT_customersController"].ToString();
    
                var response = await this.apiService.GetList<T_customers>(urlApi, prefix, controller);
    
                if (!response.IsSuccess)
                {
                    this.IsRunning = false;
                    this.IsRefreshing = false;
                    await Application.Current.MainPage.DisplayAlert(
                        Languages.Error,
                        response.Message,
                        "OK");
                    return;
                }
    
                this.CustomerList = (List<T_customers>)response.Result;
                this.RefreshCustomerList();
    
                this.IsRefreshing = false;
                this.IsRunning = false;
    
            }
            public void RefreshCustomerList()
            {
                var userList = MainViewModel.GetInstance().Login.ListUsers;
                    var customerSelected = this.CustomerList.Select(e => new CustomerItemViewModel
                    {
                        LastName= e.LastName,
                        Id_Customer = e.Id_Customer,
                        Name= e.Name,
                        Id_User = e.Id_User,
                        Mail= e.Mail,
                        Phone = e.Phone ,
    
                        Profile_Picture = userList.FirstOrDefault(u => u.Id_User  == e.Id_User ).Profile_Picture
    
                    });
    
                    this.Customers = new ObservableCollection<CustomerItemViewModel>(
                    customerSelected.OrderBy(e => e.Name));
            }
    

    On RefreshCustomerList() method, the Profile_Picture is obtained from a validation.

    And this is How I have my Xaml Page

                            <ListView                    
                                HasUnevenRows="True"
                                IsPullToRefreshEnabled="True"
                                IsRefreshing="{Binding IsRefreshing}"                    
                                ItemsSource="{Binding Customers}"
                                RefreshCommand="{Binding RefreshCustomerCommand}">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
                                            <Grid>
                                                <!--<Grid.GestureRecognizers>
                                                    <TapGestureRecognizer Command="{Binding CustomerPageCommand}"/>
                                                </Grid.GestureRecognizers>-->
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width=".05*"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto"/>
                                                </Grid.RowDefinitions>
    
                                                <StackLayout
                                                    Grid.Column="1"
                                                    HorizontalOptions="StartAndExpand"
                                                    VerticalOptions="CenterAndExpand">
                                                    <Label
                                                        FontAttributes="Bold"
                                                        FontSize="14"
    
                                                        Text="{Binding Name}"      <--Here is the Customer Detail.
    
                                                        TextColor="LightGray"
                                                        VerticalTextAlignment="End"/>
                                                    <StackLayout
                                                        HorizontalOptions="StartAndExpand"
                                                        Orientation="Horizontal"
                                                        VerticalOptions="Start">
                                                        <Label
                                                            FontAttributes="Bold"
                                                            FontSize="12"
                                                            HorizontalOptions="Start"
    
                                                            Text="{Binding LastName}"   <--Here is the Customer Detail.
    
                                                            TextColor="LightGray"
                                                            VerticalTextAlignment="Start"/>
                                                        <Label
                                                            FontAttributes="Bold"
                                                            FontSize="12"
                                                            HorizontalOptions="StartAndExpand"
    
                                                            Text="{Binding Phone}"  <--Here is the Customer Detail.
    
                                                            TextColor="LightGray"
                                                            VerticalTextAlignment="Start"/>
                                                    </StackLayout>
                                                </StackLayout>
                                                <Image
                                                    Grid.Column="2"
                                                    HorizontalOptions="StartAndExpand"
    
                                                    Source="{Binding Profile_Picture}"       <--Here is the User Detail.
    
                                                    VerticalOptions="Center"
                                                    WidthRequest="20"/>
                                            </Grid>
                                        </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
    

    I Hope it helps to any One whith this.

    Thanks for all your help... @voidstream And @yelinzh , you really help me to get the Solution....

Sign In or Register to comment.