Database T4 Templating Tricks

I love T4 templates. It’s incredible how much canned code can be generated automatically for you. T4 can not only generate static code, but it can do much more like access the database through SMO. All you need to do is define the server and database like so:

<#@ assembly name="Microsoft.SqlServer.ConnectionInfo" #>
<#@ assembly name="Microsoft.SqlServer.Smo" #>
<#@ assembly name="Microsoft.SqlServer.Management.Sdk.Sfc" #>

<#@ import namespace="Microsoft.SqlServer.Management.Smo" #>
lt;#@ import namespace="Microsoft.SqlServer.Management.Common" #>


<#
 var server = new Server("localhost");
 var db = server.Databases["MYDB"];
#%gt;

In this database, suppose you have a Types table that’s static. Your types table may be a ID/Name pairing in the database, which you reference either using magic numbers (the ID since it’s static) or do a Name cross reference. With T4, instead of using numbers or strings, you could hard-code the values by querying the table and creating constants for each type:

public class Constants
{

      public partial class SettingTypes
      {
<#
         var catDS = db.ExecuteWithResults("select ID, Name from dbo.SettingTypes where Visible = 1");
         foreach (DataRow row in catDS.Tables[0].Rows)
         {
#>
         public const long <#= row["Name"].ToString() #> = <#= row["ID"].ToString() #>;
<#
         }
#>
      }
}

Above using the global DB server reference, we use the ExecuteWithResults method to run a specified query against that database, and return the results as a DataSet. The system processes the results and generates “public const long XYZ = 1” where XYZ is the name in the table, and 1 is the ID. We can generate whatever we want; for instance, you could generate just the names as strings by changing the constant to:

public const string <#= row["Name"].ToString() #> = "<#= row["Name"].ToString() #>;

This produces a result similar to the following (using our first example):

public class Constants
{
   public partial class SettingTypes
   {
       public const long AppName = 1;
       public const long URLRedirect = 2;
       .
       .
   }
}

Or as (using our second example):

public class Constants
{
   public partial class SettingTypes
   {
       public const long AppName = "AppName";
       public const long URLRedirect = "URLRedirect";
       .
       .
   }
}

Through our application, we may have had references to “AppName” or “URLRedirect” or whatever common values this type table would have (this is unfortunately a very generic example and I hope you see how it’s applicable). With our new approach, we can do:

Utilities.LookupSettingType(Constants.SettingTypes.AppName);

We now have a compiled-time reference. This helps to provide extra checking for situations where we may remove entries from the SettingsTypes table. Any code references to it would now produce a compile error.

It’s also possible to connect to a database table’s metadata too, to generate the appropriate metadata for that table. The SMO API has table and column objects, used like below that can generate the metadata to a generated class.

public partial class ApplicationDetails
{
<#
         var ncTable = db.Tables["ApplicationDetails"];

         foreach (Column column in ncTable.Columns)
         {
#>
            public const string <#= column.Name #> = "<#= column.Name #>";
<#
         }
#>
}

This would generate a class like the following:

public partial class ApplicationDetails
{
   public string ID = "ID";
   public string Name = "Name";
   public string Description = "Description";
}

Now we can change any static reference to compile time references by referring to the description column as Constants.ApplicationDetails.Description, rather than just “Description”. It’s also possible to pull other metadata in too, such as the data type and more. If you can’t get everything you need, you can try to query the INFORMATION_SCHEMA views to get any additional information.

One useful utility I created with T4 was a generic ReferenceTypes class, where all of my _Types tables are defined in a static class. This processes all of the tables in the database, generating a static reference to the name of a reference table.

public partial class ReferenceTypes
{

<# foreach (Table table in db.Tables) {
            if (table.Name.EndsWith("Types")) {
#>
         public const string <#= table.Name #> = "<#= table.Name #>";
<#
            }
         }
#>

}

Sounds good? I’ve found a lot of good uses for T4 templates; I even use it to generate a starter shell to create stored procedures, application repositories, started controllers and views for MVC, and more. I’ll touch base on that in another blog post but I hope I helped you see how useful T4 is.

There are some things you shouldn’t use it for. You shouldn’t use it for anything you expect to change dynamically. Because it’s generating classes that get compiled with the projects, you can’t change it from live code and expect the changes to be available. Any changes included are defined as of the last compilation of the application. Another thing that you may find out is you will attempt to implement some common task in T4, but T4 turns out to be not a good solution. I’ve run into this a couple of times.

All in all, T4 templates are great to generate common code and can really cut down on writing redundant code, while adding compile-type checking on reference data.

Advertisements

ASP.NET MVC And Client Side Lists with Kendo

In this post, I’m going to illustrate a very simple way to create client-side list-based UI’s in ASP.NET MVC. The idea with this example is to allow the ability to add a bulk number of list items that doesn’t require constantly posting back to add additional items. In this example, we’ll use Kendo UI Core framework templating capabilities, although any templating framework will do.

To start, let’s look at a very simple model:

public  class SystemTestModel
{
   public List Entities { get; set; }
}

public class SystemListEntity
{
   public string Name { get; set; }
   public string Value { get; set; }
   public bool IsDeleted { get; set; }
}

Here we have a View Model that has a list of child items. Very simple. Notice the entity has 2 properties, and an IsDeleted property, which will be illustrated later. For this example, the controller setup is simple; it reads the form posted values and rebuilds the non-deleted ones:

public ActionResult List()
{
   var model = new SystemTestModel { Entities = new List() };
   return View(model);
}

[HttpPost]
public ActionResult List(SystemTestModel model)
{
   //Remove non-deleted records - deleted from  client
   var entities = model.Entities.Where(i => i.IsDeleted == false);

   //Save entities to DB or other work
   //Reload UI
   return View(new SystemTestModel { Entities = entities.ToList() });
}

Within the view, the Name/Value pairs are rendered

<tbody id="Grid" data-last-index="@(Model.Entities.Count - 1)">
   @for (var i = 0; i < Model.Entities.Count; i++) {
     <tr>
         <td>
            <input type="text" name="@Html.NameFor(m => m.Entities[i].Name)" value="@Model.Entities[i].Name" />
            <input type="hidden" name="@Html.NameFor(m => m.Entities[i].IsDeleted)" value="@Model.Entities[i].IsDeleted" />
         </td>
         <td>
            <input type="text" name="@Html.NameFor(m => m.Entities[i].Value)" value="@Model.Entities[i].Value" />
         </td>
      </tr>
   }
</tbody>

Each server-side item is rendered using the collection-based naming syntax that MVC uses to identify collections. The name for a collection-based item looks like the server-side equivalent: Entities[X].[Field] (ie. Entities[0].Name). This is important because our client-side HTML template must do the same thing:


   <tr>
      <td>
          
          <input type="hidden" name="@Html.NameFor(m => m.Entities[-99].IsDeleted)" value="@Boolean.FalseString" />
      </td>
      <td>
          <input type="text" value="#= Value #" name="@Html.NameFor(m => m.Entities[-99].Value)" />
      </td>
   </tr>

Notice in the template the -99; the really neat thing about the NameFor helper is that the expression doesn’t need to be valid; -99 works and literally renders to the HTML as “Entities[-99].Name”. Notice that the script block is the same equivalent above, but will be used to render client-side additional elements. The HTML between the two doesn’t need to be exact, but similar. The view will use this template when the “Add” button is clicked.

What that really means is that the server may have rendered 2 name/value items, and the client can render additional pairs. Our approach is to ensure that we render the pairs in sequential order whether created from server or client, preserving that sequential order.

The view has an add button. The add button triggers the templating capability of kendo. The idea with the template is to get the HTML for the entry and replace the “-99” with the actual index. So if the server-side rendering produced 2 elements (using indexes 0 and 1), the client-side “Add” button generates items starting from index “2” and greater.

$(function () {
   //http://docs.telerik.com/kendo-ui/framework/templates/overview
   $("#NewButton").on("click", function (e) {
      var html = $("#ItemTemplate").html();
      //Get the last index, add 1 because we are adding an item at the new index
      var index = $("#Grid").data("last-index") + 1;
      $("#Grid").data("last-index", index);

      //Replace -99 with the new Index
      html = html.replace(/-99/g, index);

      //Can be used to apply data values from JS
      var template = kendo.template(html);
      var data = {}; //For now, not doing any template binding
      var content = template(data);
            
      $("#Grid").append(content);
   });
});

The first step here is get the templated HTML, and update the current index appropriately. When this UI posts back, the updated index sequence posts back the new items correctly at positions 2 and greater. When the UI reloads, we now have server-side items created from the new index, and new items can be added again.

You may have noticed the IsDeleted property; this can be used to indicate items as deleted. The UI can have a delete button, which can trigger JavaScript that can hide the entire TR tag of the item from view and update the hidden field. When posted back, a permanent delete can happen (purge from the DB if it was originally persisted).

The main goal of this approach is bulk entry of lists without having to postback to add each item, like web forms used to do.

Here is the entire View (assumes JQuery and Kendo scripts included):

@model SystemTestModel

<form action="" method="post">

   <div class="row">
      <div class="col-md-12">

         <table class="table table-bordered table-hover">
            <thead>
               <tr>
                  <th>Name
                  <th>Value
               </tr>
            </thead>
            <tbody id="Grid">
               @for (var i = 0; i < Model.Entities.Length; i++)
               {
                    <tr>
                      <td>
                         <input type="text" name="@Html.NameFor(m => m.Entities[i].Name)" value="@Model.Entities[i].Name" />
                          <input type="hidden" name="@Html.NameFor(m => m.Entities[i].IsDeleted)" value="@Model.Entities[i].IsDeleted" />
                        </td>
                         <td>
                             <input type="text" name="@Html.NameFor(m => m.Entities[i].Value)" value="@Model.Entities[i].Value" />
                           </td>
                          </tr>

               }
            </tbody>
         </table>

      </div>
   

   <div class="row">
      <div class="col-md-12">

         <button type="submit" name="Action" value="SAVE" class="btn btn-primary">
             Save 
         </button>
         <button type="button" name="Action" value="NEW" class="btn btn-default">
             New
         </button>

      </div>
   </div>

</form>

@section scripts {
   
      <script type="text/x-kendo-template">
               <tr>
                    <td>
                        <input type="text" value="#= Name #" name="@Html.NameFor(m => m.Entities[-99].Name)" />
                        <input type="hidden" name="@Html.NameFor(m => m.Entities[-99].IsDeleted)" value="@Boolean.FalseString" />
                    </td>
                     <td>
                        <input type="text" value="#= Value #" name="@Html.NameFor(m => m.Entities[-99].Value)" />
                     </td>
              </tr>
      </script>

<script type="text/javascript">
      $(function () {

         //http://docs.telerik.com/kendo-ui/framework/templates/overview
         $("#NewButton").on("click", function (e) {
            var html = $("#ItemTemplate").html();
            //Get the last index, add 1 because we are adding an item at the new index
            var index = $("#Grid").data("last-index") + 1;
            $("#Grid").data("last-index", index);

            //Replace -99 with the new Index
            html = html.replace(/-99/g, index);

            //Can be used to apply data values from JS
            var template = kendo.template(html);
            var data = {}; //For now, not doing any template binding
            var content = template(data);
            
            $("#Grid").append(content);
         });

      });
   </script>

}

And Controller:

public class SystemListEntity
   {
      public string Name { get; set; }

      public string Value { get; set; }

      public bool IsDeleted { get; set; }

   }


    public class SystemController : BaseController
    {

         public ActionResult List()
         {
            var model = new SystemTestModel { 
                          Entities = new List<SystemListEntity>() };

            return View(model);
         }

         [HttpPost]
         public ActionResult List(SystemTestModel model)
         {
            var entities = model.Entities.Where(i => i.IsDeleted == false);

            //Save entities

            //Reload UI
            return View(new SystemTestModel { Entities = entities.ToList() });
         }
}

Kendo MVVM Sample in ASP.NET MVC

Kendo MVVM is exciting in UI application development framework that binds a JavaScript model to an HTML view. At the core of the MVVM framework is a JavaScript model definition that defines members of the view model that the view will use. For instance, here is a simplified model:

var vm = kendo.observable({ Name: "" });

The idea here is that the model has a Name property that will be bound. The kendo.observable call wraps the model and prepares it for two-way binding in the UI. In our example, this property can be bound to a control like:

<input type="text" name="Name" data-bind="value:Name" />

Our name property in our view model is bound to the textbox, and the data-bind attribute is responsible for wiring everything up. When the textbox value changes, the view model is updated, and vice versa. This is the main benefit of two-way binding. Taking this and looking at a more complicated example, we can use the same approach within ASP.NET MVC. Below is a sample complex example:

var viewModel = kendo.observable({

                     ID: null,
                     ParentItemCategoryTypeID: null,
                     Code: null,
                     Name: null,
                     IsActive: null,
                     Sequence: null,

                     categoriesDataSource: new kendo.data.DataSource({
                           data: @(Html.Raw(JsonConvert.SerializeObject(Model.ItemCategories)))
                     }),

                     onClear: function (e) {
                           this.set("ID", null);
                           this.set("ParentItemCategoryTypeID", null);
                           this.set("Code", null);
                           this.set("Name", null);
                           this.set("IsActive", false);
                           this.set("Sequence", null);
                     },
.
.
});

This view model has 6 properties (ID, Code, Name, etc.); it also has one complex property (a kendo data source that is used to bind to a grid) and an event handler. I’ll come back to the kendo data source later.

At this point, the init method copies the values from the view model (defaulted to null) to input and other HTML elements in the view. In order to link an element to the view model, it requires the data-bind attribute, like the following samples:

<input type="text" class="form-control" data-bind="value:Name" />

Since MVC HTML helpers render out textboxes, we can use TextBox for with the data_ notation. The data_bind attribute renders as data-bind, so we have complete data- attribute support.

@Html.TextBoxFor(i => i.Name, new { @class = "form-control", data_bind = "value:Name" )

Other uses of data-bind attribute can be to wire up click event handlers, bind listviews to kendo data sources, control the visibility of an HTML element, and more.

<button id="ClearFormButton" type="reset" class="btn btn-warning" data-bind="click: onClear">Clear</button>

<tbody id="listview" data-role="listview" data-template="ListItemTemplate" data-selectable="true" data-bind="source:categoriesDataSource, events:{change:onListChange}">

<div data-bind=”visible:showSection”>

The “click” and “events” binding wire up an event handler to a function in the view model, which handles the event. In the event handler, the this pointer refers to the view model, also providing an event argument that gives you access to the underlying control as well. There are many types of other bindings, such as “css”, “visible”, etc. On init, the values from the view model are wired up to each control, and any change within the input control also updates the view model back. The view model has a get/set method to retrieve and use, or update, the view model.

Notice how data-bind for the listview is categoriesDataSource; this is a kendo.data.DataSource object defined on the viewmodel. Interestingly enough, this object takes a URL to a web service or JSON/JavaScript objects. Using Json.NET, the code above (duplicated below) serializes an array into a JavaScript, the following DataSource definition:

categoriesDataSource: new kendo.data.DataSource({
                data: @(Html.Raw(JsonConvert.SerializeObject(Model.ItemCategories)))
        }),

Is rendered as the following:

categoriesDataSource: new kendo.data.DataSource({
                data: [{"ID": 1, "Name": "ABC", ...}]
        }),

What ties the view to the model is the kendo.init method:

kendo.init("body", viewModel);

Now our view is bound to our model, and everything is initialized appropriately.

Adding Security To Html Helpers

I know the new MVC 5 HTML tag attributes for rendering ASP.NET widgets is all the rage, but there are a lot of useful approaches to using the server-side HTML helpers.  One simple extension method we are going to look at is adding control level security.  Often within our applications, we have a means of providing UI security at the control level.  We may, for instance, hide a control if the user doesn’t belong to a certain role.  It’s really simple to add this as an extension to IHtmlString, which is what HTML tag helpers do.  First, let’s look at how this might be used:

@Html.TextBoxFor(i => i.AccountID).IfInRole("ADMIN")

Notice how our textbox has an IsVisible method; this checks if the user is in the ADMIN role, and if so, it does the following:

public static IHtmlString IfInRole(this IHtmlString html, string role)
{
    if (HttpContext.Current == null)
       return html;

    if (HttpContext.Current.User.IsInRole(role);
       return html;
    else
       return new MvcHtmlString("");
}

In this method, if the user doesn’t have permissions, it outputs a blank string instead of the original HTML, thus providing some level of control security. We could use claims to do this, or some other security feature; it really doesn’t matter what is used behind the scenes. Also, we could also provide some default template to use if the control is hidden, as a blank space may not be optimal. This can especially be the case if you are using Twitter Bootstrap, because your form may look like:

Account @Html.TextBoxFor(i => i.AccountID, new { @class = "form-control" })

And thus a wrapper around it like:

@if (Html.IsInRole("Admin")) {
  
..
}

Or using a lambda template might be better. When there is supporting HTML wrapping the HTML Helper, showing or hiding may be a little more complicated depending on your design. I hope you see from this simple example how you can add some security features into your application using the old-school HTML helpers.

Kendo UI Core and DropDownListFor

Kendo UI Core supports data attribute initialization of its widgets. This initialization approach is largely created for it’s MVVM capabilities, but also can be used for server-side approaches too, which in turn can be used with ASP.NET MVC HTML helpers. The setup may be a little different than you are used to.

Please note: Although Telerik has MVC wrappers already created and ready for you to develop with, these come with the licensed version of the product and are not available through the Kendo UI Core license.

To begin, let’s look at how we’d setup the dropdownlist as an HTML widget without and use of the server.

<select id="reasonID" data-role="dropdownlist" data-option-label="-Select Reason-" data-value="">
  <option selected="selected" value="">-Select Reason-
  <option value="1">Entered in Error
  <option value="2">Removed
</select>

In our example, a select element with a pre-defined list of options is wrapped with the kendo dropdownlist widget. It’s initialized via the data-role attribute, indicating it’s a dropdownlist widget. Next, it defines options that the widget supports. Most of the attributes on the widget that you would configure through the JavaScript API can be defined here, but the syntax differs sometimes (for instance, the optionLabel property you would use in JS initialization is data-option-label in data attribute initialization). If you run into an issue, I was able to find what I needed online so far.

Telerik has some documentation on data attribute initialization here.

The dropdownlist widget can use a textbox as the source, and can also wire data up using JSON via local JavaScript API of via AJAX if you like. I’ve stuck with a select because I’m using the MVC DropDownListFor widget, and to get this widget to render the correct content that I needed, I had to use the following configuration:

@Html.DropDownListFor(
      i => i.ReasonTypeID,      
      Model.ReasonTypes, 
      new
      {
           data_role="dropdownlist", 
           data_option_label="-Select Reason-", 
           data_value=(Model.Receiving.ShrinkTransactionTypeID.HasValue ? Model.Receiving.ShrinkTransactionTypeID.Value.ToString() : ""), 
           style="width:100%;" })

Most of this is standard. The third parameter of DropDownListFor provides HTML attributes to the rendered select option. Here we define the role data attribute used for initialization. The next attribute defines the option label, and the data_value attribute defines the selected value, which is interesting. We already define what’s selected via the lambda expression pointing to our model. However, that’s used to render the selected attribute. What I found is that to cover all selection scenarios (including the default “Select Something” item) is to add the value attribute too, which the widget uses to perform the selection. The code above manually checks for null and converts to an empty string if no value present.

In case you didn’t notice, note how the HTML attribute use data_role, particularly the underscore. The convention that MVC uses is underscore (supported by the language), which is converted to a dash during the rendering process.

Understanding Game Design: Currencies

Within any specific game, there are various forms of currency, but it usually works out that there are two to three types of currency. The first type of currency, which I’ll call the primary currency, is the most easy to accrue. It usually exists within the game and is collected during the game play. For instance, for an endless runner game, the currency is in the path of the player waiting to be collected. For a city or civilization building game, currency is produced by a factory, mine, etc. and slowly builds up over time. These “factories” can be improved to yield a better economic output.

A secondary form of currency is rarer to collect. It doesn’t normally appear in the game, but can be collected in various ways: the most common way is through purchasing online. Other ways are usually as a form of daily reward, or lifetime achievements (for instance, as a form of reward for doing X action a lot of times). Sometimes, there is a third rare currency available to enable certain special actions, which can only usually be purchased.

Some examples of game currencies are the following:

  • Clash of Clans – Primary currency exists as gold/elixir, and secondary currency exists as gems. Primary currency is earned over time as produced by gold mines and elixir stations. Gems can be used to speed up the progress.
  • Boom Beach – Primary currency exists as gold for purchases, wood/stone/iron for producing buildings. Diamonds are available as a secondary currency and can be used to speed through the game.
  • Spiderman Unlimited – The primary currency are vials, with a secondary currency of ISO-8. Vials are collected during the course of running in the game, while ISO-8 is earned for completing levels.

During the game, the “economies of scale” usually favor a quicker accumulation of the primary currency, a slower accumulation of a secondary currency, and a purchase only accumulation of a tertiary currency. If you are unfamiliar with the term “Economies of Scale”, is defined as the following in Wikipedia:

In microeconomics, economies of scale are the cost advantages that enterprises obtain due to size, output, or scale of operation, with cost per unit of output generally decreasing with increasing scale as fixed costs are spread out over more units of output.

… For example, a large manufacturing facility would be expected to have a lower cost per unit of output than a smaller facility, all other factors being equal, while a company with many facilities should have a cost advantage over a competitor with fewer.

While we aren’t dealing with businesses or manufacturing, from a game design perspective, economies of scale can refer to paid vs. free users. There will be users that buy the game or pay for in-game currency to get ahead faster in the game, while other users will take a slower track and earn all currency. A good economy of scale with these two types of users should obviously slant to players willing to pay money in order to take the fast track, while making sure to offer an incentive to play the game for free users.

Incentives appear in many forms; some are the following examples:

  • They may be daily rewards for coming back to play the game day in and day out.
  • Special game modes can be made available that offer a higher level of currency than usual, but which is only available for a short period of time. These add some variances to the game

Single Page Binding with Kendo UI ListView

If you’ve looked at the demos on the Kendo UI site, you’ll notice the ListView and DataSource combination are a pretty capable combination. The ListView gives you full control over the user interface, while supporting common functionality like paging, sorting, and more. The DataSource provides read and update functionality to a local or remote data source, even giving you full control over these processes (for instance, you can use JQuery directly for AJAX communication). The pager natively pages through the contents of the listview automatically for you. The three widgets offer great functionality for the developer.

While the combination works well, I personally ran into a snag using the Kendo UI core version (open source). With the pager component natively paging the content, the data source required a complete dataset downloaded from the server. If your ListView will be presenting 30 records, all 30 must be retrieved from the server; if 3,000, all 3,000 must be retrieved from the server. Now natively the data source control supports server paging, most examples illustrated using the Telerik MVC wrappers for handling the server-side processing, and as such, I wasn’t sure whether it was supported. If it works, I would recommend using the kendo pager as it offers the smoothest navigation; but if not, this workaround worked just as well, with some added effort. In order to get around this, I ended up using the Bootstrap Paginator plugin.

The bootstrap paginator allows you control over the number of pages to show, and provide delegation on user interaction, with the example below.

$('#pager').bootstrapPaginator({
            currentPage: 1,
            totalPages: 10,
            onPageClicked: function(e, evt, type, page){
                //Reload the listview - listview uses custom AJAX option
                #("#listview").data("kendoListView").dataSource.read();
            }
        });

The currentPage option sets the current page in the list, within the range of total pages. It’s possible to preload these from an MVC model, especially when you factor in postbacks (the pager needs reinitialized on postbacks), as in the following:

{
   currentPage: @Model.CurrentPage,
   totalPages: @Model.TotalPages
}

When the user clicks on a page, it fires the onPageClicked callback handler, which subsequently triggers an AJAX action back to the server. We’ll need the new page index from the event handler; we can get it directly from the plugin, or store the current index in a hidden variable. Either way, this piece of information needs passed back to the server.
If you looked in the example online, it has a custom AJAX action as shown below.

$("#listview").kendoListView({
    dataSource: {
       transport: {
           read: function(o) {
              var index = // Get index from hidden variable or wherever

              $.ajax({
                  type: "post",
                  url: "@Url.Action("Action", "Controller"),
                  data: { index: index, otherParams: "OTHER PARAMS" },
                  success: function(d) { o.success(d); },
                  error: function(d) { o.error(d); }
              }); 
              
           }
       }
    }
});

Here we trigger the postback to the server, and pass in the list of form data values, as well as the currently selected page index. Since the items per page is hard-coded in this scenario (at say 10, for example), we can quickly calculate the starting index and ending index of the current page.

There are many ways to implement this solution; this is one quick, simple way to introduce paging with large lists of data, where each page is dynamically loaded at paging time.

UITableView Part 2 – DataSources and Sources

In every programming language and operating system, there is always a grid control, which needs data. How the grid gets it data varies slightly; however, conceptually the grid gets the data through a data source. Sometimes the data source is the raw data itself, and sometimes it’s a wrapper around the data, which the wrapper offers some additional functionality. In iOS, there are two ways to bind the UITableView, through a UITableViewDataSource object and a UITableViewSource object. Both forementioned classes, similar in nature, are delegate classes that act as an intermediary between the underlying data and the tableview. In iOS, a delegate is a construct much different from the class that drives the behavior of the tableview. In Xamarin iOS, the UITableViewSource is a class with a bunch of optional methods. Overriding particular methods allow a developer to tap into certain functionality of and receive feedback from the tableview.

This post is going to discuss how to bind to a UITableView, and assumes you are familiar with the basic features of iOS and the UITableView. To begin, in order to use a UITableViewSource for a TableView in Xamarin iOS, follow these steps.

First, create a new class that inherits from UITableViewSource:

public class MySource : UITableViewSource

Next, override the following method:

UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)

The GetCell method is responsible for creating and populating a UITableViewCell that the UI will return to the current user, and may look like the following implementation:

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
	var cell = tableView.DequeueReusableCell ("StringIdentifier");
	if (cell == null)
		cell = new UITableViewCell(UITableViewCellStyle.Default, "StringIdentifier");

	//Load data into cell from data source

	return cell;
}

First we see if a cell has already been created for this identifier. The iOS framework will try to reuse an existing cell if it’s already created. If it isn’t created, then the cell is instantiated and returned. Additionally, the RowsInSection method is used to determine the number of rows in the current section. RowsInSection is useful for grouping of tables (which is supplied in the constructor of the UITableViewController, but that’s for another discussion). When the table is grouped, the RowsInSection method needs to return the number of rows (in integer form) for the given groups at the specified index path (since the NSIndexPath contains the current section and the current data item pointers).

The GetCell and RowsInSection methods are the most critical methods because it controls how the data is loaded in the UI.

There are plenty of other useful methods to know about to. For instance, if you want to handle the click of a row, handle the RowSelected event:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    //DO something

    tableView.DeselectRow (indexPath, true); // iOS convention is to remove the highlight
}

The UITableViewSource has methods for overriding the height of the row, and header/footer (if using grouping), as well as change the current view used for the header and footer. For instance, the view could be changed to use an image as the header and footer, as I wrote about before.

Note that the UITableViewSource class doesn’t retain your data source; you need to store the data in a variable so it can be retrieved through the index path later. Also, note that the source needs to be created for every controller you may want to use it in, leading to a lot of repetition.

Now I’m not one for repetition; I really don’t like the idea of writing boilerplate code just for the sake of writing boilerplate code. Therefore, I decided to create a reusable base class that abstracts most of the functionality away. It takes away a lot of the repetitiveness, while also offering the full functionality. To use it, all you need to do is inherit from Nucleo.UI.BaseUITableViewSource, and override the GetCellIdentifier and PopulateCell methods, and set the Data or GroupedData properties (depending on whether the table is grouped or not). This means you really could define a UITableViewSource like:

public class MySource : Nucleo.UI.BaseUITableViewSource
{
    public override string GetCellIdentifier() { return "My"; }

    public override MyClass PopulateCell(UITableViewCell cell, T dataItem, NSIndexPath path)
    {
        //Cell is already dequeued or created, only populate the cell here
    }
}

The process of creating the cell is abstracted away for you; however, if you are using a custom cell (more on this later), then you can override the CreateNewCell class and return your custom cell, and cast the cell reference in the PopulateCell method. Additionally, all of the grouping functionality is handled for you automatically by setting GroupedData property; RowsInSection and SectionFor methods, all used for grouping, are already wired up.

If you want to view the full code sample, you can do so from here. You can also find my project where I have this code at my Nucleo Mobile bitbucket.org repository.