DEV Community

Akash Kava for Web Atoms

Posted on

How to write Templates in Xamarin.Forms with TypeScript?

List View

Same as in XAML, you can create DataTemplate easily in TSX as shown below, syntax is not very different then that of Xaml.


import Bind from "@web-atoms/core/dist/core/Bind";
import XNode from "@web-atoms/core/dist/core/XNode";
import { AtomXFControl } from "@web-atoms/core/dist/xf/controls/AtomXFControl";
import XF from "@web-atoms/xf-controls/dist/clr/XF";
import AtomXFContentPage from "@web-atoms/xf-controls/dist/pages/AtomXFContentPage";
import ListViewModel from "./ListViewModel";

export default class List extends AtomXFContentPage {

    public viewModel: ListViewModel;

    public create() {
        this.viewModel = this.resolve(ListViewModel);

        this.render(
            <XF.ContentPage title="List Sample">
                <XF.ListView itemsSource={Bind.oneWay(() => this.viewModel.movies.value)}>
                    <XF.ListView.itemTemplate>
                        <XF.DataTemplate>
                            <XF.ViewCell>
                                <XF.Label text={Bind.oneWay((x) => x.data.name)}/>
                            </XF.ViewCell>
                        </XF.DataTemplate>
                    </XF.ListView.itemTemplate>
                </XF.ListView>
            </XF.ContentPage>
        );
    }

}
Enter fullscreen mode Exit fullscreen mode

Same as that of Xaml, you can define DataTemplate with a ViewCell or any element that is derived from Cell

Template Selector

Writing template selector requires little different syntax.

        this.render(<XF.ContentPage title="List with Template Selector">
            <XF.ListView itemsSource={Bind.oneWay(() => this.viewModel.movies.value)}>
                <WA.AtomTemplateSelector.templateSelector>
                    <WA.AtomTemplateSelector selector={(d: IMovie) => /horror/i.test(d.genre)
                        ? 1 : 0}>
                        {/* Template 0 */}
                        <XF.DataTemplate>
                            <XF.TextCell
                                text={Bind.oneWay((x) => x.data.name)}
                                textColor="black"
                                />
                        </XF.DataTemplate>
                        {/* Template 1 */}
                        <XF.DataTemplate>
                            <XF.TextCell
                                text={Bind.oneWay((x) => x.data.name)}
                                textColor="red"
                                />
                        </XF.DataTemplate>
                    </WA.AtomTemplateSelector>
                </WA.AtomTemplateSelector.templateSelector>
            </XF.ListView>
        </XF.ContentPage>);
Enter fullscreen mode Exit fullscreen mode

As you can see, WA.AtomTemplateSelector is a placeholder element, which will simply set template based on some condition.

selector condition evaluates and returns an index of templates enclosed within AtomTemplateSelector.

Collection View

In collection view, you can write templates without cells, same as in Xaml.

   <XF.CollectionView 
       itemsSource={Bind.oneWay(() => this.viewModel.movies.value)}>
       <XF.CollectionView.itemTemplate>
            <XF.DataTemplate>
                <XF.Label text={Bind.oneWay((x) => x.data.name)}/> 
            </XF.DataTemplate>
       </XF.CollectionView.itemTemplate>
   </XF.CollectionView>
Enter fullscreen mode Exit fullscreen mode

How does it work?

XF.DataTemplate translates to Xamarin.Forms.DataTemplate and it uses constructor with factory to create elements only when needed.

How to create control template?

Creating control template is exactly same with little difference in CLR Xamarin binding syntax.

Following example displays, how to change ControlTemplate of AtomField in form.

   <WA.AtomForm.fieldStyle>
      <XF.ControlTemplate>
         <XF.Grid>
            <XF.Grid.rowDefinitions>
               <XF.RowDefinition height="Auto"/>
                  <XF.RowDefinition/>
                  <XF.RowDefinition height="Auto"/>
            </XF.Grid.rowDefinitions>
            <XF.Label
               text={X.TemplateBinding("Label")}
               textColor="Green"
               />
            <XF.ContentPresenter
               { ... XF.Grid.row(1)}
               />
         </XF.Grid>
     </XF.ControlTemplate>
   </WA.AtomForm.fieldStyle>
Enter fullscreen mode Exit fullscreen mode

Binding of Xamarin.Forms is actually replaced with X.Binding and X.TemplateBinding.

In above example, XF.ControlTemplate refers to ControlTemplate of Xamarin.Forms. Templates are optimized to be reused and there is no performance lag even when they are written in TypeScript.

Interoperability

Web Atoms allows you to use, both JavaScript as well as Xamarin Bindings on TemplateBinding as well as Binding. However, little care must be taken based on source object. To bind properties of classes written in C# you must use X.Binding and X.TemplateBinding respectively. To bind objects created in JavaScript, you must use Bind.oneWay/twoWays syntax.

Top comments (0)