Create an accordion/bindable stacklayout using custom controls in Xamarin

By: Admin

While custom controls can reduce maintenance headaches, one of the main reasons to use custom controls is to maximize code sharing and minimize code duplication. In this article, we will build an accordion and bindable stacklayout for applications developed in Xamarin.

ACCORDION

Several buttons or labels are stacked upon one another. At most, one of them can be active. When a button is active, the space below the button is used to display a paned window. This is usually constrained by the width of labels. When opened, the pane shifts labels under the clicked label down according to the height of that window. Only one button or pane combination can be active at any one time; when a button is selected, any other active panes cease to be active and are hidden. The active pane may have scrollbars.

Creating Accordion

To create an “Accordion.xaml” file and write a code based on the requirement:

The Accordion.xaml code is shown below:

<ContentView
    x:Class="MobileX.Controls.Accordion"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <ContentView.Content>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid
                x:Name="accordionGrid"
                Padding="0,5"
                VerticalOptions="Center">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="25" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Label
                    x:Name="accordionImage"
                    Grid.Column="0"
                    Margin="5,4,5,0"
                    Style="{StaticResource ListViewRightArrow}" />
                <Label x:Name="accordionTitleLabel" Grid.Column="1" />
            </Grid>
            <Frame
                x:Name="accordionContent"
                Grid.Row="1"
                Padding="30,5,0,5"
                BackgroundColor="Transparent"
                HasShadow="False" />
        </Grid>
    </ContentView.Content>
</ContentView>

In this example, we created a ContentView xaml file. You can create controls for whatever you want to display under the accordion.

The Accordion class is an extension of the ContentView class in Xamarin.Forms. TheAccordion user control code is shown below:

public partial class Accordion : ContentView
    {
        public Accordion()
        {
            InitializeComponent();
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += (s, e) =>
            {
                AccordionTapped();
            };
            accordionGrid.GestureRecognizers.Add(tapGestureRecognizer);
        }
 
        private bool isCollapsed;
 
        public bool IsCollapsed
        {
            get => isCollapsed;
            set
            {
                isCollapsed = value;
                if (!isCollapsed)
                {
                    accordionImage.RotateTo(90, 180, Easing.Linear);
                    accordionContent.FadeTo(1, 400, Easing.SpringIn);
                }
                else
                {
                    accordionImage.RotateTo(0, 180, Easing.Linear);
                    accordionContent.FadeTo(0, 400, Easing.SpringOut);
                }
                accordionContent.IsVisible = !isCollapsed;
            }
        }
 
        public string Title
        {
            get => accordionTitleLabel.Text;
            set => accordionTitleLabel.Text = value;
        }
 
        public Style TitleStyle
        {
            get => accordionTitleLabel.Style;
            set => accordionTitleLabel.Style = value;
        }
 
        private void AccordionTapped()
        {         
            IsCollapsed = !IsCollapsed;
        }
 
        public View AccordionContent
        {
            get { return accordionContent.Content; }
            set { accordionContent.Content = value; }
        }
    }

Accordion (). is the constructor.

  • IsCollapsed
  • Title
  • TitleStyle
  • AccordionTapped
  • AccordionContent

The properties above are created for our accordion user control.

Give the namespace of the accordion.xaml file path in the page you are going to use this accordion user control. Label it with an accordion tag.

xmlns:controls=”clr-namespace:Mobile.Controls”

Begin coding whatever you want to display inside the accordion user control.

<controls:Accordion
  Title="Project Sites"
  IsCollapsed="True"
  TitleStyle="{StaticResource AccordionTitle}"
  VerticalOptions="FillAndExpand">
    <controls:Accordion.AccordionContent>
    </controls:Accordion.AccordionContent>
</controls:Accordion>

BINDABLE STACKLAYOUT

Bindable Stacklayout is an extension of Stacklayout which will support DataTemplates, Horizontal and Vertical layouts in a dynamic manner.
Bindable Stack Layout

public class BindableStackLayout : StackLayout { }

 

When using this class, we have to create a Bindable Property.

Bindable Property:

A bindable property’s value is tracked by the Xamarin.Forms property system. You can read more about Bindable Properties in this article. There are several properties we need to code.

Adding the exposed property:

First, we need to create a regular property for our bindable property.

public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

Adding the BindableProperty field:

To create the BindableProperty, we need to create a read-only BindableProperty field. Ideally, the name of this field is the same as the regular property that we created. We’ll just add property at the end of it.

 

public static readonly BindableProperty ItemsSourceProperty;

Set the field with BindableProperty.Create() method. This Create () method takes numerous parameters. Some of these values can be null.

public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create
(nameof(ItemsSource),						
typeof(IEnumerable<object>), 
typeof(BindableStackLayout), 
default(IEnumerable<object>), 
BindingMode.TwoWay, 
propertyChanged: ItemsSourceChanged);

There are several parameters being set:

  • PropertyName – the name of our exposed property as a string.
  • ReturnType – the return type of our property.
  • DeclaringType – the type declaring this BindableProperty.
  • DefaultBindingMode – the binding mode our property should have.
  • PropertyChanged – the specified callback method to be fired after the property has changed. This will receive 3 parameters: bindable(the current control class),oldValue(the old value of the property) and newValue(the newest value of the property).

Adding the callback method:

Lastly, we need to create a callback. We can either do this inline or by creating a callback method. We’ll do it by creating a method:

private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
      var itemsLayout = (BindableStackLayout)bindable;
      itemsLayout.SetItems();
}

 

Consuming the BindableProperty:

Now that we have set up the bindable properties, what we want to do now is to use them. If we go to our xaml page, we can now use our custom control:

controls:BindableStackLayout
       IsVisible="{Binding ProjectSiteListIsNotEmpty}"
       ItemsSource="{Binding ProjectSitesList}"
       SelectedItem="{Binding SelectedProjectSite, Mode=TwoWay}">
</controls:BindableStackLayout>

Copyright © 2018 alligatortek. All rights reserved.