Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Xamarin Forms Sketch demonstrating data binding (without strings, to nested objects, to unlimited number of fields) and common app/sketch code. Note: remove the .cs from the file name, it is only there to make GitHub format it as C#
using Xamarin.Forms;
// Additional guidance: see http://vincenth.net/blog/archive/2014/11/27/how-to-share-xamarin-forms-data-binding-code-across-xamarin-sketches-and-apps-without-using-strings.aspx
// NOTE: Once support for creating classes is added to Xamarin Sketches,
// there is no need for this Tuple + enum + BindName + regular expression workaround;
// you can then simply create design data classes in the Sketch and bind to that using
// the same syntax in both projects and sketches, e.g.:
// SetBinding(..., (Person boundPerson) => boundPerson.Name)
// BindName helper function for use with binding to design data in Sketches.
// Usage: SetBinding(..., BindName(SomeEnum.SomeValue))
// Maps an enum property name value to a Tuple ItemX property name.
// Maps 7th and later properties to nested Tuples in Item7.
//
// Use this regular expression to convert SetBinding() code from sketch to project:
// E.g. SetBinding(..., BindName(Person.Name) will become SetBinding(..., (Person boundPerson) => boundPerson.Name
// Search: SetBinding\s*\((?<bindableProperty>[^,]+)\s*,\s*BindName\((?<class>[^\.\)]*)\.(?<property>[^\.\)]*)\)
// Replace: SetBinding(${bindableProperty}, (${class} bound${class}) => bound${class}.${property}
//
// Use this regular expression to convert SetBinding() code from project to sketch:
// E.g. SetBinding(..., (Person boundPerson) => boundPerson.Name will become SetBinding(..., BindName(Person.Name)
// Search: SetBinding\s*\((?<bindableProperty>[^,]+)\s*,\s*\(\s*(?<class>\w*)\s+bound\k<class>\s*\)\s*=>\s*bound\k<class>\.(?<property>\w*)
// Replace: SetBinding(${bindableProperty}, BindName(${class}.${property})
Func<Enum, string> BindName = (Enum propertyName) =>
{
const int MaxTupleItems = 7;
int fieldIndex = int.Parse(propertyName.ToString("D"));
string bindName = "";
while (fieldIndex >= MaxTupleItems)
{
bindName += "Item" + MaxTupleItems.ToString() + ".";
fieldIndex -= (MaxTupleItems - 1);
}
bindName += "Item" + fieldIndex.ToString();
return bindName;
};
// Names of bindable classes with properties as enum names with values for Sketch design data
// Set the first value in each enum to 1 to map to Tuple Item1
// Subsequent items will map to subsequent Tuple fields
// You can overcome the limit of 7 properties in a Tuple by making the 7th property a nested Tuple,
// which can then contain properties 7 through 12. You can keep nesting tuples to add more properties.
enum Name
{
First = 1,
Last
};
enum Person
{
Image = 1,
Name,
Description,
Property4,
Property5,
Property6,
Property7,
Property8,
Property9
};
// Design data for Sketch.
// Each tuple in the list represents a Person class with a nested Name class, which is represented by a nested Tuple.
// Property7..9 are represented by a nested Tuple in Item7, demonstrating how to overcome the limit of 7 properties in a Tuple.
var persons = new List<Tuple<UriImageSource,Tuple<string, string>,string, string, string, string, Tuple<string, string, string>>> {
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1s07h2W") }, new Tuple<string, string>("Miguel", "de Icaza"), "CTO and Co-founder", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value\nNo strings, just code :-)")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1rYGvGU") }, new Tuple<string, string>("Nat", "Friedman"), "CEO and Co-founder", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value\nUse Class.Property")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://photos1.meetupstatic.com/photos/member/2/4/a/6/member_74169382.jpeg") }, new Tuple<string, string>("Vincent", "Hoogendoorn"), "Developer", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value\nCompiler checks name")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1EhFsao") }, new Tuple<string, string>("Stephanie", "Schatz"), "SVP of Sales and Customer Success", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value\nDot notate: Class.Property")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1oIYpso") }, new Tuple<string, string>("Joanne", ""), "VP of Marketing", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound field value")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/10CbVZE") }, new Tuple<string, string>("Joseph", ""), "Director of Developer Relations and Co-founder", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound field value")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1vCRbKh ") }, new Tuple<string, string>("Rob", ""), "VP of Business Development", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1rPp1vm") }, new Tuple<string, string>("Bryan", ""), "Vice President of Education Services", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value")),
Tuple.Create(new UriImageSource { Uri = new Uri("http://bit.ly/1sXguu1") }, new Tuple<string, string>("Jason", ""), "Team Lead - Xamarin.Forms", "4", "5", "6", new Tuple<string, string, string>("7", "8", "9th bound property value")),
};
var personTemplate = new DataTemplate(() =>
{
// Start of common App/Sketch code fragment #1 *****************************
var image = new Image {
WidthRequest = 100,
HeightRequest = 100
};
image.SetBinding(Image.SourceProperty, BindName(Person.Image));
var firstNameLabel = new Label();
firstNameLabel.SetBinding(Label.BindingContextProperty, BindName(Person.Name));
firstNameLabel.SetBinding(Label.TextProperty, BindName(Name.First));
var lastNameLabel = new Label {
TextColor = Color.Gray
};
lastNameLabel.SetBinding(Label.BindingContextProperty, BindName(Person.Name));
lastNameLabel.SetBinding(Label.TextProperty, BindName(Name.Last));
var titleLabel = new Label();
titleLabel.SetBinding(Label.TextProperty, BindName(Person.Description));
var ninthFieldLabel = new Label {
TextColor = Color.White,
BackgroundColor = Color.Purple
};
ninthFieldLabel.SetBinding(Label.TextProperty, BindName(Person.Property9));
var nameLayout = new StackLayout {
Children = { firstNameLabel, lastNameLabel },
Orientation = StackOrientation.Horizontal
};
var textLayout = new StackLayout {
Children = { nameLayout, titleLabel, ninthFieldLabel }
};
var cellLayout = new StackLayout {
Padding = 10,
Orientation = StackOrientation.Horizontal,
Children = { image, textLayout }
};
// End of common App/Sketch code fragment #1 *******************************
var cell = new ViewCell {
View = cellLayout,
};
return cell;
});
var page = new ContentPage();
// Start of common App/Sketch code fragment #2 *****************************
var searchBar = new SearchBar { Placeholder = "Search ..." };
var listView = new ListView {
ItemTemplate = personTemplate,
ItemsSource = persons,
RowHeight = 110
};
var layout = new StackLayout {
Children = {
searchBar,
listView
}
};
page.Padding = new Thickness(0, 20, 0, 0);
page.Content = layout;
// End of common App/Sketch code fragment #2 *******************************
RootPage.Children.Add(page);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.