Forum Xamarin Xamarin.Forms

How to create bindable event handler in custom view cell

shubham14shubham14 USMember ✭✭
edited September 2018 in Xamarin.Forms

Hi,
I have created native ViewCellRenderer for view cell that is being used in list view For UWP by following Microsoft article Customizing a ViewCell.
The article explains how to create bindable properties for a view cell that can be displayed using the native controls. What I want is to be able to create a bindable event handler so that I can bind this event with native UWP code say Tapped event of Textbock.

Example- On the tapped event of Textblock 'Name' i want to navigate to some another page. The navigation logic is written inside the view model for the page where I am using the list view with custom view cell. How can I create a bindable event handler in custom view cell so that I could bind it with the Tapped event of native code.

Best Answer

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    Firstly create a custom ViewCell with a TappedCommand as a bindable property:

    public class NativeCell : ViewCell
    {
        ...// Other bindable properties
    
        public static readonly BindableProperty TappedCommandProperty =
            BindableProperty.Create("TappedCommand", typeof(Command), typeof(NativeCell), null);
    
        public ICommand TappedCommand
        {
            get { return (ICommand)GetValue(TappedCommandProperty); }
            set { SetValue(TappedCommandProperty, value); }
        }
    
    }
    

    Then in the view cell renderer we can use XamlBehaviors to bind the TextBlock's Tapped event to the command which we defined in the custom view cell:

    <Application.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="ListViewItemTemplate">
                <Grid>                
                    <TextBlock Text="{Binding TextName}" >
                    <interactivity:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Tapped">
                            <core:InvokeCommandAction  Command="{Binding TappedCommand}"/>
                        </core:EventTriggerBehavior>        
                    </interactivity:Interaction.Behaviors>
                    </TextBlock>
                </Grid>
            </DataTemplate>
        </ResourceDictionary>
    </Application.Resources>
    

    At last we can use this custom view cell in the page:

    <StackLayout>
        <ListView x:Name="listView" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:NativeCell TextName="{Binding TextName}" TappedCommand="{Binding TappedCommand}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
    

    And the corresponding model:

    public class Model
    {
        public string TextName { get; set; }
    
        public ICommand TappedCommand { get; set; }
    
        public Model(INavigation Navigation)
        {
            TappedCommand = new Command(() =>
            {
                Navigation.PushAsync(new SecondPage());
            });
        }
    }
    

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    Firstly create a custom ViewCell with a TappedCommand as a bindable property:

    public class NativeCell : ViewCell
    {
        ...// Other bindable properties
    
        public static readonly BindableProperty TappedCommandProperty =
            BindableProperty.Create("TappedCommand", typeof(Command), typeof(NativeCell), null);
    
        public ICommand TappedCommand
        {
            get { return (ICommand)GetValue(TappedCommandProperty); }
            set { SetValue(TappedCommandProperty, value); }
        }
    
    }
    

    Then in the view cell renderer we can use XamlBehaviors to bind the TextBlock's Tapped event to the command which we defined in the custom view cell:

    <Application.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="ListViewItemTemplate">
                <Grid>                
                    <TextBlock Text="{Binding TextName}" >
                    <interactivity:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Tapped">
                            <core:InvokeCommandAction  Command="{Binding TappedCommand}"/>
                        </core:EventTriggerBehavior>        
                    </interactivity:Interaction.Behaviors>
                    </TextBlock>
                </Grid>
            </DataTemplate>
        </ResourceDictionary>
    </Application.Resources>
    

    At last we can use this custom view cell in the page:

    <StackLayout>
        <ListView x:Name="listView" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:NativeCell TextName="{Binding TextName}" TappedCommand="{Binding TappedCommand}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
    

    And the corresponding model:

    public class Model
    {
        public string TextName { get; set; }
    
        public ICommand TappedCommand { get; set; }
    
        public Model(INavigation Navigation)
        {
            TappedCommand = new Command(() =>
            {
                Navigation.PushAsync(new SecondPage());
            });
        }
    }
    
  • shubham14shubham14 USMember ✭✭

    Thanks a lot that is what i was looking for.
    Really appreciated your detail explanation with nice code snippet for each component.

  • ricardoventuraricardoventura Member ✭✭

    @LandLu said:
    Firstly create a custom ViewCell with a TappedCommand as a bindable property:

    public class NativeCell : ViewCell
    {
        ...// Other bindable properties
    
        public static readonly BindableProperty TappedCommandProperty =
            BindableProperty.Create("TappedCommand", typeof(Command), typeof(NativeCell), null);
    
        public ICommand TappedCommand
        {
            get { return (ICommand)GetValue(TappedCommandProperty); }
            set { SetValue(TappedCommandProperty, value); }
        }
    
    }
    

    Then in the view cell renderer we can use XamlBehaviors to bind the TextBlock's Tapped event to the command which we defined in the custom view cell:

    <Application.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="ListViewItemTemplate">
                <Grid>                
                    <TextBlock Text="{Binding TextName}" >
                    <interactivity:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Tapped">
                            <core:InvokeCommandAction  Command="{Binding TappedCommand}"/>
                        </core:EventTriggerBehavior>        
                    </interactivity:Interaction.Behaviors>
                    </TextBlock>
                </Grid>
            </DataTemplate>
        </ResourceDictionary>
    </Application.Resources>
    

    At last we can use this custom view cell in the page:

    <StackLayout>
        <ListView x:Name="listView" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:NativeCell TextName="{Binding TextName}" TappedCommand="{Binding TappedCommand}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
    

    And the corresponding model:

    public class Model
    {
        public string TextName { get; set; }
    
        public ICommand TappedCommand { get; set; }
    
        public Model(INavigation Navigation)
        {
            TappedCommand = new Command(() =>
            {
                Navigation.PushAsync(new SecondPage());
            });
        }
    }
    

    Hey,
    I can't install the package "XamlBehaviors"... somebody knows why? I'm stucked :neutral:

Sign In or Register to comment.