Search code examples
c#xamlxamarin.formsitemsource

Xamarin Forms - Make custom cell bind to original listview itemsource when calling event "ItemSelected"


I have searched around and I dont think I am finding the answer to my question. I am new to xamarin so i hope I am using the correct terminology. I am experimenting with custom cells in listviews. My aim is to reuse the custom cell throughout multiple parts of my application but when I use the event "ItemSelected" it comes back with the bindings to the custom cell and not my original listview itemsource bindings. I understand why I think but I am unsure how to bind the ItemSelected to the original source. Am I using the right method here? I am completely lost if I am honest.

This is my custom cell code:

public partial class ListCell : ViewCell
    {
        public static readonly BindableProperty LabelHeaderProperty = BindableProperty.Create("LabelHeader", typeof(string), typeof(ListCell));
        public string LabelHeader
        {
            get { return (string)GetValue(LabelHeaderProperty); }
            set { SetValue(LabelHeaderProperty, value); }
        }
        public static readonly BindableProperty LabelSmallProperty = BindableProperty.Create("LabelSmall", typeof(string), typeof(ListCell));
        public string LabelSmall
        {
            get { return (string)GetValue(LabelSmallProperty); }
            set { SetValue(LabelSmallProperty, value); }
        }
        public ListCell()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            BindingContext = new
            {
                LabelHeader = this.LabelHeader,
                LabelSmall = this.LabelSmall
            };
        }
    }

Here is my ListView

<ListView x:Name="MyListView"
                ItemsSource="{Binding Items}"
                VerticalOptions="FillAndExpand"
                HasUnevenRows="true"
                IsPullToRefreshEnabled="true"
                ItemSelected="OnItemSelected"
                SeparatorVisibility="None">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <extensions:ListCell LabelHeader="{Binding Description}"
                                         LabelSmall="{Binding Description}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Thank you very much in advance :)


Solution

  • According to your code, when binding to a custom cell type's BindableProperty instances, the UI controls displaying the BindableProperty values should use the OnBindingContextChanged override to set the data to be displayed in each cell.

     public class ListCell:ViewCell
    {
        Label headerLabel, smallLabel;
        public static readonly BindableProperty LabelHeaderProperty = BindableProperty.Create("LabelHeader", typeof(string), typeof(ListCell),"name");
        public string LabelHeader
        {
            get { return (string)GetValue(LabelHeaderProperty); }
            set { SetValue(LabelHeaderProperty, value); }
        }
        public static readonly BindableProperty LabelSmallProperty = BindableProperty.Create("LabelSmall", typeof(string), typeof(ListCell),"small label");
        public string LabelSmall
        {
            get { return (string)GetValue(LabelSmallProperty); }
            set { SetValue(LabelSmallProperty, value); }
        }
    
        public ListCell()
        {
            StackLayout stack = new StackLayout { Orientation=StackOrientation.Horizontal};
            headerLabel = new Label { FontAttributes = FontAttributes.Bold };
            smallLabel = new Label();
            stack.Children.Add(headerLabel);
            stack.Children.Add(smallLabel);
            View = stack;
        }
        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();
    
            if (BindingContext != null)
            {
                headerLabel.Text = LabelHeader;
                smallLabel.Text = LabelSmall;
               
            }
        }
    }
    
     <ListView
                x:Name="listView"
                ItemSelected="listView_ItemSelected"
                ItemsSource="{Binding items}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <local:ListCell LabelHeader="{Binding Name}" LabelSmall="{Binding description}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
    

    But You can use TextCell in ListView's DataTemplate directly, don't need to create custom viewcell.

    <ListView ItemsSource="{Binding items}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Detail="{Binding description}" Text="{Binding name}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
    

    About using TextCell, you can take a look:

    https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/data-and-databinding#binding-cells