Wednesday, November 22, 2017

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

Leave a Comment

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.

2 Answers

Answers 1

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

Answers 2

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             }         }      } } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment