Xamarin.Forms Carousel – Part 2: Converting the pieces into a MVVM/XAML architecture

I’m on an exciting journey, getting up to speed with Xamarin.Forms. Being mostly a ASP.NET developer since more than a decade, i used some great resources out there to learn the concepts of Xamarin.Forms (using the fantastic preview chapters of Charles Petzold’s book) as well as best practices for a MVVM/IOC based architecture. For the latter the wonderful blog „Adventures in Xamarin Forms“ by Jonathan Yates was an indispensable resource full of insights and creative inspiration.

This is part 2 of the series „Creating a Xamarin.Forms Carousel“

Part 1: The basic parts
Part 2: Converting the pieces into a MVVM/XAML architecture
Part 3: Reloading the Carousel’s content from a WebService
Part 4: Design-Fun in XAML

 

In my last post i analyzed Chris Riesgo’s recipe for a Xamarin.Forms Carousel component.

While i really like his overall approach, it’s just a demo solution, and i clearly don’t want to setup all that code in my projects for every page that contains a Carousel control. So i need some refactoring.

What i like to achieve for my solution is

  1. Keeping the flexibility to add any content to the Carousel
  2. Create the layout of the Component in XAML
  3. Be able to change the scrolled elements type in XAML
  4. Add some navigation commands to enable e.g. timer controlled automatic scrolling

 

Create the Carousel layout in XAML

I will start with creating a ContentView in XAML which takes the part of defining the Carousel component’s layout. In Chris’ demo solution, this was created in a function on the Page. The difficult part of doing the same in XAML are the Constraints of the RelativeLayout, namely the part that places the PagerIndicator within the Carousel:

 

 

Especially the part combining the parent’s height with the sibling’s height is nothing that can directly be done in XAML. At least nothing i know about. So i came up with a somehow simplified solution, placing the PageIndicator, centered in a surrounding StackLayout at 90% of the Carousel element’s height. This works for me and is easy to customize.

For now, i will concentrate on the Carousel with a „Dots“ NavigationIndicator, as that’s what i want at first. So here’s the XAML of the CarouselViewDots component – please note the imported namespace xmlns:corelayout, which points to the CarouselLayout class we previously have moved into our core component:

 

 

In the CodeBehind of this component i added some bindable properties, to customize the appearance of the Carousel. Remember that we want to include this component in our XAML pages where the Carousel shall appear. The properties are
  1. DotColor
  2. DotSize
  3. ItemTemplate (type DataTemplate) which is forwarded to the CarouselLayout object
  4. ScrollToIndex (allows for program controlled scrolling)
Here’s the code:

 

The ItemTemplate Property is directly forwarded to the ItemTemplate property of the CarouselLayout object, as well as the SelectedIndex property, which is also maintained by the internal CarouselLayout and shall be readonly in our XAML component. The bindable ScrollToIndex property is calling the ScrolltoIndexCommand when changed, which calls the CarouselLayout objects native ScrollToAsync method, leaving the animated scrolling to that component. Don’t let the name of that property fool you. It only ever Scrolls one element, because the CarouselLayout class sets its internal ScrollView to Paging mode, thus always ever scrolling one element at a time.
OK, fine – we will also put this generic Component into our core project, so now we have our Carousel component ready to be included in some XAML pages.

Create a first Carousel Demo Page in XAML

 Let’s now do a demo page, almost identical to Chris’ demo, but with a StackLayout above and beyond the Carousel and one more StackLayout, holding Buttons to navigate back and forth:

 

Please note the „corelayouts“ namespace, included from our core project.
The Carousel component itself is included by just the lines of XAML, with the BindingContext set to the Carousel property:

 

Also note that the contents of the Carousel component are defined by setting the ItemTemplate in XAML. In this example i add a CarouselItemView ContentView, as you see in the code above. We will get back to this shortly.
Now we need some basic plumbing for our page to work, first of all a ViewModel, implementing the Bindable Properties for our page. As i want the Carousel functionality kept separate from the Page’s ViewModel, i created a separate ViewModel for the Carousel, named CarouselDemoViewModel and instantiated it in the page’s ViewModel, for simplicity’s sake by just creating it, not leveraging the IOC container of my overall architecture:

 

The CarouselDemoViewModel is as simple as shown below and holds just a List of CarouselItemViewModel objects, which are also held quite simple, with a Title, Background and ImageSource property, thus being able to control slides with different background colors and an optional Image:


 

Getting back to the Page’s ViewModel,  you can see, the CarouselDemoPageViewModel derives from a CarouselViewModelBase, which is the base class i created for my CarouselViewModels, implementing the general properties and commands to control any of my Carousels. Here’s the code of the CarouselViewModelBase, which also resides in the core project:

 

Edit (20.02.2016)

I got asked what the ViewModel class CarouselItemViewModelBase is all about. In fact i missed to explain this. So here we go:

There’s nothing magic in this class. It’s just a base class for all my CarouselItemViewModels, implementing general properties i expect all CarouselItemViewModels to need, as well as the interface ITabProvider, which i don’t use yet, but on which the tabbed layout demonstrated by Chris Riesgo relies:

 

For completeness‘ sake, here the ITabProvider interface:

 

With these ViewModels in place, the Carousel should be ready to go. As mentioned above, as a first example i added a ContentView of type CarouselItemView to the Carousel. This ContentView is taken from Chris Riesgo’s sample solution and thus created in pure C# code:

 

Later we will add another ContentView, then created in XAML. Luckily, in Xamarin.Forms we do have the choice.

 Starting up the app, we get this simple demo layout, with the initial state (left) and to the right after clicking twice on the „Next“ button, which is bound to the SwitchCarouselForwardCommand which, as you might remember, in turn is implemented in our CarouselViewModelBase class:
Xamarin.Forms Carousel DemoPage

Xamarin.Forms Carousel DemoPage

 

Xamarin.Forms Carousel DemoPage - scrolled

Xamarin.Forms Carousel DemoPage – scrolled

 

Cool! Now having this up and running, the fun begins. Let’s play with it – why not add an image slider?

Creating a CarouselImageView

All we have to do are 2 things:

  1. Create a new ContentView displaying an image
  2. Change the DataTemplate of our corelayouts:CarouselViewDots Component to that view

This time we will be creating the ContentView in XAML. We use a simple StackLayout and put a Image-Control inside, binding its Source property to the ViewModel’s ImageSource property:

 

 

Please remember that our Demo-ViewModel is already prepared and has the ImageSource property already initialized to some images:

 

As – for now – we want to display static images, we need to add some images to our platform projects. In our iOS project, we put the images into the Resources folder. For Droid the images go into the Resource/drawable folder.

Now that all is prepared, we can switch our Carousel over to display the new CarouselImageView.
Let’s go to our XAML page and change the ItemTemplate:

 

 

Let’s run the App and view some nice pics:

Xamarin.Forms Carousel DemoPage with CarouselImageView

Carousel with CarouselImageView

 

Xamarin.Forms Carousel DemoPage with CarouselImageView scrolled

Carousel with CarouselImageView scrolled

 

Awesome! That’s it – whether we want to creates Slides of local content or fetch data from the Web – our component is prepared. The beauty of Chris Riesgo’s approach cannot be shown in images – you have to feel how the slides snap into their place. Being able to pack this stuff into a handy XAML component shows the power of Xamarin Forms.

In my next post i will continue having fun (hopefully :)) and load some images from Flickr on-the-fly.