Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set up different footers for TableSections when using a Custom TableView Renderer

I am using a renderer to allow me to set a custom footer in my TableView. The renderer works but I would like to have the capability to set up different footers for the different table sections. For example one footer for table section 0 and another for table section 1, all the way up to table section 5.

Here's the XAML that I am using:

           <!-- <local:ExtFooterTableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">-->
                <TableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">
                <TableSection Title="Cards1">
                    <ViewCell Height="50">
                        <Label Text="Hello1" />
                    </ViewCell>
                    <ViewCell Height="50">
                        <Label Text="Hello2" />
                    </ViewCell>
                </TableSection>
                <TableSection Title="Cards2">
                    <TextCell Height="50" Text="Hello"></TextCell>
                </TableSection>

                </TableSection>
        <!--    </local:ExtFooterTableView>-->
            </TableView>

and here is the C# class and renderer:

public class ExtFooterTableView : TableView
{
    public ExtFooterTableView()
    {
    }
}

and:

   using System;
using Japanese;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(ExtFooterTableView), typeof(Japanese.iOS.ExtFooterTableViewRenderer))]
namespace Japanese.iOS
{
    public class ExtFooterTableViewRenderer : TableViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
        {
            base.OnElementChanged(e);
            if (Control == null)
                return;

            var tableView = Control as UITableView;
            var formsTableView = Element as TableView;
            tableView.WeakDelegate = new CustomFooterTableViewModelRenderer(formsTableView);
        }


        private class CustomFooterTableViewModelRenderer : TableViewModelRenderer
        {
            public CustomFooterTableViewModelRenderer(TableView model) : base(model)
            {
            }

            public override UIView GetViewForFooter(UITableView tableView, nint section)
            {
                Debug.WriteLine("xx");
                if (section == 0)
                {
                    return new UILabel()
                    {
                        // Text = TitleForFooter(tableView, section), // or use some other text here
                        Text = "abc",
                        TextAlignment = UITextAlignment.Left
                        // TextAlignment = NSTextAlignment.NSTextAlignmentJustified
                    };
                }
                else
                {
                    return new UILabel()
                    {
                        // Text = TitleForFooter(tableView, section), // or use some other text here
                        Text = "def",
                        TextAlignment = UITextAlignment.Left
                        // TextAlignment = NSTextAlignment.NSTextAlignmentJustified
                    };
                }
            }

        }
    }
}

The code works but I would like to find out how I can set up a different footer text for different sections in the XAML. Something like this:

From what I see it looks like the code is partly there TitleForFooter(tableView, section) but I am not sure how to use it and how I could set it up. Note that I am not really looking for a view model solution. I would be happy to be simply able to specify the section footer text as part of the TableView XAML.

I'd appreciate if anyone could give me some advice on this.

like image 364
Samantha J T Star Avatar asked Nov 13 '17 16:11

Samantha J T Star


2 Answers

First of all, in order to be able to specify the section footer text in XAML - simplest option would be to create a bindable property in TableSection. But as TableSection is sealed, we can't derive it to define our custom bindable properties.

So, the next option is to create a attached bindable property.

public class Ex
{
    public static readonly BindableProperty FooterTextProperty =
        BindableProperty.CreateAttached("FooterText", typeof(string), typeof(Ex), defaultValue: default(string));

    public static string GetFooterText(BindableObject view)
    {
        return (string)view.GetValue(FooterTextProperty);
    }

    public static void SetFooterText(BindableObject view, string value)
    {
        view.SetValue(FooterTextProperty, value);
    }
}

Next step would be to update renderer to retrieve this value for every section:

private class CustomFooterTableViewModelRenderer : TableViewModelRenderer
{
    public CustomFooterTableViewModelRenderer(TableView model) : base(model)
    {
    }

    public override UIView GetViewForFooter(UITableView tableView, nint section)
    {
        return new UILabel()
        {
            Text = TitleForFooter(tableView, section), // or use some other text here
            Font = UIFont.SystemFontOfSize(14),
            ShadowColor = Color.White.ToUIColor(),
            ShadowOffset = new CoreGraphics.CGSize(0, 1),
            TextColor = Color.DarkGray.ToUIColor(),
            BackgroundColor = Color.Transparent.ToUIColor(),
            Opaque = false,
            TextAlignment = UITextAlignment.Center
        };
    }

    //Retrieves the footer text for corresponding section through the attached property
    public override string TitleForFooter(UITableView tableView, nint section)
    {
        var tblSection = View.Root[(int)section];
        return Ex.GetFooterText(tblSection);
    }
}

Sample Usage

<local:ExtFooterTableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">
    <TableSection Title="Cards1" local:Ex.FooterText="Sample description">
        <ViewCell Height="50">
            <Label Margin="20,0,20,0" Text="Hello1" />
        </ViewCell>
        <ViewCell Height="50">
            <Label Margin="20,0,20,0" Text="Hello2" />
        </ViewCell>
    </TableSection>
    <TableSection  Title="Cards2" local:Ex.FooterText="Disclaimer note">
        <TextCell Height="50" Text="Hello"></TextCell>
    </TableSection>
</local:ExtFooterTableView>

enter image description here

like image 179
Sharada Gururaj Avatar answered Dec 17 '22 20:12

Sharada Gururaj


It is very simple. you need to add the bindable property for pass value from XAML to CustomRenderer in CustomControl like this:

Customer TableView

public class ExtFooterTableView : TableView
{
    public ExtFooterTableView()
    {
    }
}

Xaml control code

<local:ExtFooterTableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">

Renderer class

using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using yournamespace;
using System.ComponentModel;

[assembly: ExportRenderer(typeof(ExtFooterTableView), typeof(FooterTableViewRenderer))]
namespace yournamespace
{
    public class FooterTableViewRenderer : TableViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
        {
            base.OnElementChanged(e);
        }


        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            var view = (ExtFooterTableView)Element;

            if (e.PropertyName == ExtFooterTableView.IntentProperty.PropertyName)
            {
                string intent = view.Intent;
                // Do your stuff for intent property
            }

            if (e.PropertyName == ExtFooterTableView.HasUnevenRowsProperty.PropertyName)
            {
                bool hasUnevenRows = view.HasUnevenRows;
                // Do yout stuff for HasUnevenRow
            }
        }

    }
}
like image 45
Pavan V Parekh Avatar answered Dec 17 '22 19:12

Pavan V Parekh