xamarin.formsgallerybindable

Xamarin Forms - Using bindable layout to access different parts of the model


I'm trying to setup a gallery of images, that also features the ability to click on the image to show/hide a grid with image description, using the MVVM process.

However, i think my model, view model and view is not correctly setup because i am only able to display the images in the stacklayout if i use BindableLayout.ItemsSource="{Binding GalleryList.Gallery}" in the top stacklayout, but not able to access the other parts of the class, i.e. only the Gallery list.

So essentially, I cant access InfoGridVisible binding, since the it can't find/reach it? (i'm not sure to be honest).

Here is a snippet of my work so far:

View - testpage.xaml:


<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="testproject.Pages.testpage"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:styles="clr-namespace:testproject.Styles"
    xmlns:behaviours="clr-namespace:testproject.ViewModels"
    mc:Ignorable="d"
    xmlns:pancakeview="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
    xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
    BackgroundColor="Orange"
    x:Name="Root">
      <ContentPage.Content>
            <ScrollView>
                <Grid 
                    Grid.Row="3">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>

                    </Grid.ColumnDefinitions>

                    <!--PROBLEM STARTS HERE -->
                    <StackLayout x:Name="GalleryStk" Grid.Row="1" Orientation="Vertical" BindableLayout.ItemsSource="{Binding GalleryList.Gallery}" Margin="10,0,10,0">
                        <BindableLayout.ItemTemplate>
                            <DataTemplate>
                                <Grid RowSpacing="5" ColumnSpacing="0">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="AUTO"/>
                                        <RowDefinition Height="AUTO"/>
                                    </Grid.RowDefinitions>



                                    <Frame x:Name="ImageFrame" CornerRadius="20" Padding="0" IsClippedToBounds="True" Grid.Row="0">
                                        <Image Source="{Binding Image}" Aspect="AspectFill" Grid.RowSpan="2" HorizontalOptions="Center" VerticalOptions="Center">
                                            <Image.GestureRecognizers> 
                                                <TapGestureRecognizer BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}" Command="{Binding TapCommand}"/>
                                            </Image.GestureRecognizers>
                                        </Image>
                                    </Frame>
                                    <!--<Image Source="ShadowOverlay" Grid.RowSpan="2"  Aspect="Fill" VerticalOptions="End" HorizontalOptions="Fill" />-->

                                    <Grid x:Name="InfoGrid"  RowSpacing="10" ColumnSpacing="10" Grid.Row="0" IsEnabled="False" IsVisible="{Binding GalleryList.InfoGridVisible, Source={x:Reference InfoGrid}}">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="AUTO"/>
                                            <RowDefinition Height="25"/>
                                        </Grid.RowDefinitions>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="5"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="AUTO"/>
                                        </Grid.ColumnDefinitions>

                                            <BoxView Color="Black" Opacity="0.5" CornerRadius="20" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Row="0" Grid.RowSpan="5" Grid.ColumnSpan="3"/>
                                            <Label Text="{Binding Title}" Padding="10,10,0,0" Grid.Row="0" Grid.ColumnSpan="3" Style="{StaticResource TitleLabel}" LineBreakMode="NoWrap"/>


                                        <!--<controls:CircleImage Source="{Binding ProfileImage}" Aspect="AspectFill" Grid.Row="1" Grid.Column="0" WidthRequest="25" HeightRequest="25" />-->
                                            <Label Text="{Binding Description}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Padding="10,0,10,0" Grid.Row="1" Grid.RowSpan="4" Grid.ColumnSpan="3" Style="{StaticResource HandleLabel}"/>
                                            <!--<Button Text="See More" x:Name="ExpandContractButton" Clicked="ExpandContractButton_Clicked" Padding="10,0,10,0" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="3"/>-->


                                        <!--<StackLayout Orientation="Horizontal"  VerticalOptions="Center" Grid.Column="2" Grid.Row="1" Spacing="5">
                                            <Image Source="Eye"/>
                                            <Label Text="{Binding ViewCount, StringFormat='{0:N0}'}" Style="{StaticResource HandleLabel}" />
                                            <Label Text="views" Style="{StaticResource BodyLabel}"/>
                                        </StackLayout>-->
                                    </Grid>

                                </Grid>
                            </DataTemplate>
                        </BindableLayout.ItemTemplate>

                        </StackLayout>
                    </Grid>
            </ScrollView>
    </ContentPage.Content>
</ContentPage>

Code behind for view - testpage.xaml.cs

public partial class testpage : ContentPage
    {
        private Image _galleryImage;
        public Grid GalleryInfoGrid;
        private static testpage _instance;

        public UserProfileViewModel vm { get; }

        public static testpage Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new testpage();

                return _instance;
            }
        }

        public testpage()
        {
            InitializeComponent();
            vm = new UserProfileViewModel();
            BindingContext = new UserProfileViewModel();
            //var _galleryInfoGrid = (Grid)Root.FindByName("InfoGrid");
            //_galleryInfoGrid.IsEnabled = true;
            //_galleryInfoGrid.IsVisible = true;

        }

Model:

    {
        public List<GalleryImage> Gallery { get; set; }
        public string InfoGridVisible;
        public string InfoGridEnabled;
    }

    public class GalleryImage
    {
        public string Title { get; set; }
        public string Image { get; set; }
        public string Description { get; set; }
    }

Services (data):

public class ProfileService
    {
        private static ProfileService _instance;


        public static ProfileService Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new ProfileService();

                return _instance;
            }
        }
public GalleryList GetGallery()
        {
            return new GalleryList
            {
                InfoGridEnabled = "False",
                InfoGridVisible = "False",
                Gallery = new List<GalleryImage>
                {
                    new GalleryImage { Title="sevilla01.jpg", Image = "sevilla01.jpg", Description="Description1Description1Description1Description1 Description1Description1Description1 Description1Description1" },
                    new GalleryImage { Title="sevilla02.jpg", Image = "sevilla02.jpg", Description="Description2 Description1Description1Description1Description1Descript ion1Description1"  },
                    new GalleryImage {Title="sevilla03.jpg", Image = "sevilla03.jpg", Description="Description3Description1Description1Description1"  },
                    new GalleryImage {Title="sevilla04.jpg", Image = "sevilla04.jpg", Description="Description4Description1Description1" },
                    new GalleryImage {Title="sevilla05.jpg", Image = "sevilla05.jpg", Description="Description5Description1" },
                    new GalleryImage {Title="sevilla06.jpg", Image = "sevilla06.jpg", Description="Description6" },
                    new GalleryImage {Title="sevilla07.jpg", Image = "sevilla07.jpg", Description="Description7Description1Description1Description1Description1Description1Description1Description1Description1 Description1" }
                }
            };
        }
    }

View Model - UserProfileViewModel.cs:

public class UserProfileViewModel : BindableObject
    {
        //Models
        private Profile _profile;
        private GalleryList _galleryList;
        int taps = 0;
        ICommand tapCommand;

        public UserProfileViewModel()
        {
            Profile = ProfileService.Instance.GetProfile();
            GalleryList = ProfileService.Instance.GetGallery();

            tapCommand = new Command(OnTapped);
        }

        public ICommand TapCommand
        {
            get { return tapCommand; }
        }

        void OnTapped(object s)
        {
            taps++;
            //var info1Grid = testpage.Instance.GalleryInfoGrid;
            //info1Grid.IsVisible = true;
            //info1Grid.IsEnabled = true;
            //GalleryList.InfoGridEnabled = "False";
            //GalleryList.InfoGridVisible = "False";
            Console.WriteLine("parameter: " + taps + " " + GalleryList.InfoGridVisible);
            OnPropertyChanged();
        }

        public Profile Profile
        {
            get { return _profile; }
            set
            {
                _profile = value;
                OnPropertyChanged();
            }
        }
        public GalleryList GalleryList
        {
            get { return _galleryList; }
            set
            {
                _galleryList = value;
                OnPropertyChanged();
            }
        }
    }

Apologies for the code dump, any help would be appreciated as i have been stuck on this for a few days. If there is a better method of implementing this, i would love to hear it.


Solution

  • What I want you try is something like this:

    public class GalleryList : BindableObject { 
    
        private string _InfoGridVisible { get; set; }
        private string _InfoGridEnabled { get; set; }
    
        public List<GalleryImage> Gallery { get; set; } 
        public string InfoGridVisible
        {
            get { return _InfoGridVisible; }
            set
            {
                _InfoGridVisible = value;
                OnPropertyChanged();
            }
        }
    
        public string InfoGridEnabled
        {
            get { return _InfoGridEnabled; }
            set
            {
                _InfoGridEnabled = value;
                OnPropertyChanged();
            }
        }
    }
    public class GalleryImage : BindableObject {
    
        private string _Title { get; set; }
        private string _Image { get; set; }
        private string _Description { get; set; }
    
        public string Title
        {
            get { return _Title; }
            set
            {
                _Title = value;
                OnPropertyChanged();
            }
        }
    
        public string Image
        {
            get { return _Image; }
            set
            {
                _Image = value;
                OnPropertyChanged();
            }
        }
    
        public string Description
        {
            get { return _Description; }
            set
            {
                _Description = value;
                OnPropertyChanged();
            }
        }
    }