CarouselView - A carousel of grids. Any examples?

RyanWatsonRyanWatson USMember ✭✭✭

Looking for a way to make a carouselView of grids. Anyone have any ideas or examples of how to make this happen?

Best Answer

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    I think you have to use as datatemplate a contentwiew with a grid

  • RyanWatsonRyanWatson USMember ✭✭✭

    @AlessandroCaliaro is that the only way? My data for the grid is in a List per page I see no way to bind to that data inside of a list.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Post some code

  • RyanWatsonRyanWatson USMember ✭✭✭
    edited May 2016

    ` var gridlist = new List<List>();
    foreach (var List gridData in gridlist)
    {
    var grid = new Grid();``

        foreach (var cell in gridData)
        {
            grid.Children.Add(BuildFrame(cell));
        }
    
        carouselView.Add(grid);
    }`
    

    That is the idea that I want to do. The issue though is that how do I bind to List instead of doing a SetBinding for the property? Can you bind data to a variable instead of a control?

  • RyanWatsonRyanWatson USMember ✭✭✭

    Can you Bind data in a DataTemplate to a variable?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Using a list of list as carouselview 's ItemSource?

  • RyanWatsonRyanWatson USMember ✭✭✭

    ` List<List> listOfListOfPersons = new List<List>();

            CarouselView cv = new CarouselView();
            cv.ItemsSource = listOfListOfPersons;
            cv.ItemTemplate = new DataTemplate(() => 
            {
                //Build a grid per child list. 
    
                var grid = new Grid();
    
                // Build cells in grid with ItemSourceData
    
                return grid;
            });`
    

    This is basically what I want to do. I have no clue on how to bind the ItemSource data inside the ItemTemplate to a variable instead of a control.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Casting this.BindingContext?

  • RyanWatsonRyanWatson USMember ✭✭✭

    @AlessandroCaliaro said:
    Casting this.BindingContext?

    @AlessandroCaliaro

    That is what I was thinking too... but it was Null for me.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    It should not be always null. Test the null condition and where is not null assign it to a local variable. Hope it works

  • RyanWatsonRyanWatson USMember ✭✭✭

    Yep checked it again... Always null. Doesn't make sense.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Why do you need the variable?

  • RyanWatsonRyanWatson USMember ✭✭✭

    The ItemTemplate will fire for each item in the parent list and would give me the child list to be used to build the grid for that page of the carousel.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Why you don't use a list inside the contentwiew? Can you set ItemSourceProperty of a listview? If you can, you can try to set it to "." Then create a datatemplate for the list . It's clear? I don't know if it works

  • RyanWatsonRyanWatson USMember ✭✭✭

    I want to use a grid for the layout. I like the look better. Just seems to be a little more difficult to build.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    But if you have a list of items how can you have a grid? Do you create it dinamically? You could use a grid inside a listview...

  • RyanWatsonRyanWatson USMember ✭✭✭

    Yes I am creating it dynamically. I am doing that already... I just need to supply a list of objects to a method and it builds the grid. The issue is that inside of a CarouselView I am unable to get to the list of objects.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Can you have the carouselview index in some property?

  • RyanWatsonRyanWatson USMember ✭✭✭

    The Position Property is 0 everytime the DataTemplate is fired.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    An OnAppearing event?

  • RyanWatsonRyanWatson USMember ✭✭✭

    Their is an ItemSelected and PositionSelected but they do not fire on the first page of the CarouselView.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    You should try this (very empirical)

    Pass to ItemSource a list of integers, one for every view in the carousel (the index of the view. 0,1,2...)

    Bind this value to a hidden label in the datatemplate

    Take this label.text value and use it to access a global variable of list of list that you can use to create your grid.

    Crazy I know

    I will try this evening to find a solution. Can you post a project on github?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    If you force position selected = 0? Fires?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    What is i?

  • tutugeorgetutugeorge USMember ✭✭

    You can use the control from XF. https://www.nuget.org/packages/Xamarin.Forms.CarouselView.
    we can define the data template using this it seems.

  • RyanWatsonRyanWatson USMember ✭✭✭

    @lpdavies I actually think that will work. I was trying to figure out how to do that, but didn't think of building the grid first. Tested it with just something simple and the index like that would work.

    ``
    var list = new List();

            for (int i = 0; i < 10; i++)
            {
                list.Add(new PageData()
                {
                    PageName = $"Page_{i}",
                    PageNumber = i + 1,
                    PageCounter = i
                });
            }
    
            var index = 0;
    
            CarouselView cv = new CarouselView();
            cv.ItemsSource = list;
            cv.ItemTemplate = new DataTemplate(() => 
            {
                var label = new Label()
                {
                    FontSize = 40,
                    TextColor = Color.Black,
                    Text = $"PageData_{list[index++].PageName}"
                };
    
                return label;
    
            });
    
  • seanydaseanyda GBMember ✭✭✭✭✭

    @RyanWatson said:
    @lpdavies I actually think that will work. I was trying to figure out how to do that, but didn't think of building the grid first. Tested it with just something simple and the index like that would work.

    ``
    var list = new List();

            for (int i = 0; i < 10; i++)
            {
                list.Add(new PageData()
                {
                    PageName = $"Page_{i}",
                    PageNumber = i + 1,
                    PageCounter = i
                });
            }
    
            var index = 0;
    
            CarouselView cv = new CarouselView();
            cv.ItemsSource = list;
            cv.ItemTemplate = new DataTemplate(() => 
            {
                var label = new Label()
                {
                    FontSize = 40,
                    TextColor = Color.Black,
                    Text = $"PageData_{list[index++].PageName}"
                };
    
                return label;
                
            });
    

    Yeah it works nice. I use it throughout my apps!

    @AlessandroCaliaro said:
    What is i?

    Just a counter! Make it 0 as default

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Interesting but I think it works only if you define the datatemplate in this way.
    If you create a separate class derived from a contentview and pass to itrmtemplate the type of (my contentview) how can it works?

  • seanydaseanyda GBMember ✭✭✭✭✭

    @AlessandroCaliaro pass any view over to it and it will work.. i use grids, stack layout i don't see why it wouldn't

  • RyanWatsonRyanWatson USMember ✭✭✭

    Thanks @lpdavies that worked perfectly. Just used my existing code and worked out. Got it up and running already. Thank you very much. I was making it a lot harder than it needed to be. (Next up, page indicators.)

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    @lpdavies
    excuse my ignorance. I am thinking how your solution can works in a situation like this (when I define a ContentView as DataTemplate). Where do you use your "i"? Thanks

    public class PageCarousel : ContentPage
    {
    
        public PageCarousel (ObservableCollection<string> lista)
        {
            StackLayout sl = new StackLayout ();
    
            CarouselView cv = new CarouselView ();
            cv.ItemsSource = lista;
            cv.ItemTemplate = new DataTemplate (typeof(BarcodeTemplate));
            sl.Children.Add (cv);
    
            Content = sl;
    
        }
    
        public class BarcodeTemplate : ContentView {
    
            public BarcodeTemplate(){
                Label l = new Label();
                l.FontSize = 40;
                l.SetBinding (Label.TextProperty,".");
                Content = l;
    
            }
        }
    }
    
  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    this is another solution.. App.LIST is your Model

    namespace TestBth
    {
        public class PageCarousel : ContentPage
        {
    
            public PageCarousel (ObservableCollection<string> lista)
            {
                StackLayout sl = new StackLayout ();
    
                App.CurrentCarouselView = 0;
                App.LIST = lista;
    
                CarouselView cv = new CarouselView ();
                cv.ItemsSource = lista;
                cv.ItemTemplate = new DataTemplate (typeof(BarcodeTemplate));
                cv.PositionSelected += (object sender, SelectedPositionChangedEventArgs e) => {
                    Debug.WriteLine("You have selected "+ App.LIST[(int)e.SelectedPosition]);
                };
                sl.Children.Add (cv);
    
                Content = sl;
    
            }
    
            public class BarcodeTemplate : ContentView {
    
                public BarcodeTemplate(){
                    Label l = new Label();
                    l.FontSize = 40;
                    // It's called only the first time the view appears, so I can add +1
                    l.Text = App.LIST[App.CurrentCarouselView++];
                    Content = l;
    
                }
            }
        }
    }
    
  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    @AlessandroCaliaro Why do you use a StackLayout instead of directly setting the page content to the carousel view?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    @AdrianKnight you are right. This code is a part of a more complex page that I have simplified, that has more controls in the stacklayout. In this example stacklayout is not necessary.

  • SagarPanwalaSagarPanwala USMember ✭✭

    Hi Guys,
    Is there a bug with Carousel ItemTemplate and PositionSelected event ?

    I swipe the page only in one direction, but as per my logs it shows something different. I have 5 pages, but it never goes to page 5.

    OnSelectTemplate 0
    OnSelectTemplate 0
    OnSelectTemplate 1
    OnSelectTemplate 2
    CarouselSetting_PositionSelected 1
    OnSelectTemplate 3
    CarouselSetting_PositionSelected 2
    OnSelectTemplate 4
    CarouselSetting_PositionSelected 3
    OnSelectTemplate 1
    OnSelectTemplate 4
    CarouselSetting_PositionSelected 3
    OnSelectTemplate 1

  • seanydaseanyda GBMember ✭✭✭✭✭

    @SagarPanwala said:
    Hi Guys,
    Is there a bug with Carousel ItemTemplate and PositionSelected event ?

    I swipe the page only in one direction, but as per my logs it shows something different. I have 5 pages, but it never goes to page 5.

    OnSelectTemplate 0
    OnSelectTemplate 0
    OnSelectTemplate 1
    OnSelectTemplate 2
    CarouselSetting_PositionSelected 1
    OnSelectTemplate 3
    CarouselSetting_PositionSelected 2
    OnSelectTemplate 4
    CarouselSetting_PositionSelected 3
    OnSelectTemplate 1
    OnSelectTemplate 4
    CarouselSetting_PositionSelected 3
    OnSelectTemplate 1

    Yeah this is a bug i've always had with CarouselView too.

  • SagarPanwalaSagarPanwala USMember ✭✭

    @lpdavies : Have you resolved it? If not then I need a workaround to change the selected tab.

  • seanydaseanyda GBMember ✭✭✭✭✭

    @SagarPanwala said:
    @lpdavies : Have you resolved it? If not then I need a workaround to change the selected tab.

    No I've not had any luck. :(

  • RyanWatsonRyanWatson USMember ✭✭✭

    @SagarPanwala @lpdavies

    This is the best solution I have found:

            public class LayoutTemplateSelector : DataTemplateSelector
            {
                public Dictionary<int, Grid> GridPages { private get; set; }
    
                protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
                {
                    return new DataTemplate(() =>
                    {
                        return GridPages[Convert.ToInt16(item)];
                    });
                }
            }
    
Sign In or Register to comment.