Xamarin.Tips – Changing a TableView’s Separator Color

In previous posts, I talked about the misfortunes of the Xamarin.Forms TableView. In this post, we will look at changing the separator color with a custom renderer.

For some other Xamarin.Tips on upgrading your TableView, check out these two posts on customizing the Section Titles!

Android: Xamarin.Tips – Xamarin.Forms Android Custom TableView Section Titles
iOS: Xamarin.Tips – Xamarin.Forms iOS Custom TableView Section Titles

Let’s get started with a custom view that inherits the TableView and adds a BindableProperty for our SeparatorColor:

ColoredTableView.cs

    public partial class ColoredTableView : TableView
    {
        public static BindableProperty SeparatorColorProperty = BindableProperty.Create("SeparatorColor", typeof(Color), typeof(ColoredTableView), Color.White);
        public Color SeparatorColor
        {
            get
            {
                return (Color)GetValue(SeparatorColorProperty);
            }
            set
            {
                SetValue(SeparatorColorProperty, value);
            }
        }
        public ColoredTableView()
        {
            InitializeComponent();
        }
    }

Now let’s take this view and create our renderers!

Let’s start with Android:

ColoredTableViewRenderer.cs

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

            var listView = Control as Android.Widget.ListView;
            var coloredTableView = (ColoredTableView)Element;
            listView.Divider = new ColorDrawable(coloredTableView.SeparatorColor.ToAndroid());
            listView.DividerHeight = 3;
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if(e.PropertyName == "SeparatorColor")
            {
                var listView = Control as Android.Widget.ListView;
                var coloredTableView = (ColoredTableView)Element;
                listView.Divider = new ColorDrawable(coloredTableView.SeparatorColor.ToAndroid());
            }
        }
    }
}

Basically, we take the color and apply it as a ColorDrawable, including updating when the property changes from our Forms code.

Now let’s write up our iOS renderer:

ColoredTableViewRenderer.cs

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

            var tableView = Control as UITableView;
            var coloredTableView = Element as ColoredTableView;
            tableView.SeparatorColor = coloredTableView.SeparatorColor.ToUIColor();
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if(e.PropertyName == "SeparatorColor")
            {
                var tableView = Control as UITableView;
                var coloredTableView = Element as ColoredTableView;

                tableView.SeparatorColor = coloredTableView.SeparatorColor.ToUIColor();
            }
        }
    }
}

Similarly to our Android implementation, we set the SeparatorColor of our Native UITableView on set up and when the value changes.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Xamarin.Tips – Android Shadows on Transparent Views

I talked in a previous post about creating box-shadows on iOS UIViews that are transparent that you can find here: Xamarin.Tips – iOS Shadow on Transparent UIView

This is the Android counterpart! Let’s look at putting some shadows around a view with a fully transparent background. Android presented some completely different challenges compared to iOS. In the iOS solution, we ran into issues with Shadow layers requiring something in front of it to draw the drop shadow. With Android, using a CardView from the design support library gives us access to the Elevation and CardElevation properties which CAN indeed give us shadows around our view even though it is transparent. However, that kills any border on the view. Remember that we are looking for a transparent view, with a solid border, and shadows around it.

The general approach for iOS was to draw two new layers with shadows around the right and bottom sides of the UIView. Using layers allowed us to draw outside the actual frame of the view. However, with iOS, we aren’t so lucky.

So here’s the idea:
1. Adjust the margin and padding to allow us to expand the frame of the view
2. Draw a shadow gradient on the right side
3. Draw a shadow gradient on the bottom side
4. Draw a border around what our inner frame was

Here’s what that looks like in a custom renderer (since the origin of this was a custom Xamarin.Forms view):

TransparentFrameRenderer.cs

[assembly: ExportRenderer(typeof(TransparentFrame), typeof(TransparentFrameRenderer))]
namespace YOUR_ANDROID_NAMESPACE
{
    public class TransparentFrameRenderer : Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement != null)
            {
                Element.Margin = new Thickness(-5);
                Element.Padding = new Thickness(15);
                Control.CardElevation = 0;
                Control.PreventCornerOverlap = false;
            }
        }

        protected override void OnDraw(Canvas canvas)
        {
            base.OnDraw(canvas);

            // draw border
            var strokePaint = new Paint();
            strokePaint.SetARGB(255, 255, 255, 255);
            strokePaint.SetStyle(Paint.Style.Stroke);
            strokePaint.StrokeWidth = 2;
            var rect = canvas.ClipBounds;
            var outline = new Rect(15, 15, rect.Right - 15, rect.Bottom - 15);

            var bottomPaint = new Paint();
            bottomPaint.SetStyle(Paint.Style.Fill);
            var shadowShader = new LinearGradient(0, 0, 0, 30, new Android.Graphics.Color(0, 0, 0, 100), new Android.Graphics.Color(0, 0, 0, 0), Shader.TileMode.Mirror);
            bottomPaint.SetShader(shadowShader);

            var rightPaint = new Paint();
            rightPaint.SetStyle(Paint.Style.Fill);
            var rightShader = new LinearGradient(0, 0, 20, 0, new Android.Graphics.Color(0, 0, 0, 100), new Android.Graphics.Color(0, 0, 0, 0), Shader.TileMode.Mirror);
            rightPaint.SetShader(rightShader);

            // draw the bottom and right shadows
            canvas.DrawRect(12, rect.Bottom - 12, rect.Right - 12, rect.Bottom + 3, bottomPaint);
            canvas.DrawRect(rect.Right - 12, 14, rect.Right + 3, rect.Bottom, rightPaint);
            canvas.DrawRect(outline, strokePaint);
        }
    }
}

Look at the Draw override. We are setting up 3 different paints. The first is the Paint for our white border. bottomPaint sets up for our bottom shadow using a LinearGradient as the shader, and similarly, rightPaint sets up our shadow for the right side.

Finally, we call DrawRect for both our shadows, then our border. The values in the DrawRect calls for the shadows are just examples to play with padding and size values. You can play with those as you see fit to make your view look best.

I’ve tested this in some large ListViews to test against the classic Android overdraw issue that can happen, but because it consists of 3 pretty simple strokes, I haven’t run into any performance issues. Hopefully this solution works for you!

This is NOT a complete solution, or a real reusable control, but more of a general approach to rendering shadows around a control with a transparent background.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Xamarin.Tips – Xamarin.Forms Android Custom TableView Section Titles

Xamarin.Forms’ TableView is a really useful control for displaying static content. However, it has some shortfalls. The one we will look at today is customizing the Section Title.

If you are looking for this solution on iOS, check it out here: Xamarin.Tips – Xamarin.Forms iOS Custom TableView Section Titles

Before reading ahead, I would suggest looking at your solution and assessing whether or not your TableView could be easily replaced by a ListView. I want to point this out, because ListViews have more flexibility for GroupHeader and allow you to put any control in there without having to leave your happy place that is XAML.

If that isn’t the case, keep reading; Let’s look at some simple custom renderers that can solve this problem for Android specifically.

First, let’s create a custom view that inherits TableView:

ColoredTableView.cs

 public partial class ColoredTableView : TableView
    {
        public static BindableProperty GroupHeaderColorProperty = BindableProperty.Create("GroupHeaderColor", typeof(Color), typeof(ColoredTableView), Color.White);
        public Color GroupHeaderColor
        {
            get
            {
                return (Color)GetValue(GroupHeaderColorProperty);
            }
            set
            {
                SetValue(GroupHeaderColorProperty, value);
            }
        }

        public ColoredTableView()
        {
            InitializeComponent();
        }
    }

Now we can create our Android renderer:

ColoredTableViewRenderer

[assembly: ExportRenderer(typeof(ColoredTableView), typeof(ColoredTableViewRenderer))]
namespace YOUR_ANDROID_NAMESPACE
{
    public class ColoredTableViewRenderer : TableViewRenderer
    {
       
        protected override TableViewModelRenderer GetModelRenderer(Android.Widget.ListView listView, TableView view)
        {
            return new CustomHeaderTableViewModelRenderer(Context, listView, view);
        }

        private class CustomHeaderTableViewModelRenderer : TableViewModelRenderer
        {
            private readonly ColoredTableView _coloredTableView;

            public CustomHeaderTableViewModelRenderer(Context context, Android.Widget.ListView listView, TableView view) : base(context, listView, view)
            {
                _coloredTableView = view as ColoredTableView;
            }

            public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
            {
                var view = base.GetView(position, convertView, parent);

                var element = GetCellForPosition(position);

                // section header will be a TextCell
                if (element.GetType() == typeof(TextCell))
                {
                    try
                    {
                        // Get the textView of the actual layout
                        var textView = ((((view as LinearLayout).GetChildAt(0) as LinearLayout).GetChildAt(1) as LinearLayout).GetChildAt(0) as TextView);

                        // get the divider below the header
                        var divider = (view as LinearLayout).GetChildAt(1);

                        // Set the color
                        textView.SetTextColor(_coloredTableView.GroupHeaderColor.ToAndroid());
                        textView.TextAlignment = Android.Views.TextAlignment.Center;
                        textView.Gravity = GravityFlags.CenterHorizontal;
                        divider.SetBackgroundColor(_coloredTableView.GroupHeaderColor.ToAndroid());
                    }
                    catch (Exception) { }
                }

                return view;
            }
        }
    }
}

Similar to the iOS solution, the important part is our override of GetView. What we are doing here is getting a reference to the inner child native views of our section header (why we check against the type and TextCell). Then we get our actual android TextView and the LinearLayout which is the divider below the header. From there we can change the properties of the views however we prefer. The default behavior of these views are to take the AccentColor from the android styles and use them as the BackgroundColor of the divider and the TextColor of the TextView.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Xamarin.Tips – Xamarin.Forms iOS Custom TableView Section Titles

Xamarin.Forms’ TableView is a really useful control for displaying static content. However, it has some shortfalls. The one we will look at today is customizing the Section Title. Before reading ahead, I would suggest looking at your solution and assessing whether or not your TableView could be easily replaced by a ListView. I want to point this out, because ListViews have more flexibility for GroupHeader and allow you to put any control in there without having to leave your happy place that is XAML.

If that isn’t the case, keep reading; Let’s look at some simple custom renderers that can solve this problem for iOS specifically (Android to follow).

First, let’s create a custom view that inherits TableView:

ColoredTableView.cs

 public partial class ColoredTableView : TableView
    {
        public static BindableProperty GroupHeaderColorProperty = BindableProperty.Create("GroupHeaderColor", typeof(Color), typeof(ColoredTableView), Color.White);
        public Color GroupHeaderColor
        {
            get
            {
                return (Color)GetValue(GroupHeaderColorProperty);
            }
            set
            {
                SetValue(GroupHeaderColorProperty, value);
            }
        }

        public ColoredTableView()
        {
            InitializeComponent();
        }
    }

Now let’s create a renderer in our iOS project:

ColoredTableViewRenderer.cs


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

            var tableView = Control as UITableView;
            var coloredTableView = Element as ColoredTableView;
            tableView.WeakDelegate = new CustomHeaderTableModelRenderer(coloredTableView);
        }

        private class CustomHeaderTableModelRenderer : UnEvenTableViewModelRenderer
        {
            private readonly ColoredTableView _coloredTableView;
            public CustomHeaderTableModelRenderer(TableView model) : base(model)
            {
                _coloredTableView = model as ColoredTableView;
            }
            public override UIView GetViewForHeader(UITableView tableView, nint section)
            {
                return new UILabel()
                {
                    Text = TitleForHeader(tableView, section),
                    TextColor = _coloredTableView.GroupHeaderColor.ToUIColor(),
                    TextAlignment = UITextAlignment.Center
                };
            }
        }
    }
}

Basically what we are doing is overriding the WeakDelegate of the native UITableView that is under the Xamarin.Forms TableView. That WeakDelegate is of type TableViewModelRenderer which also inherits the UITableViewSource and holds our native overrides for getting cell heights, etc. Note that this inherits NOT TableViewModelRenderer, but UnEvenTableViewRenderer. This is because my TableView has set HasUnevenRows to true. This is a business rule for my application, but if you aren’t, then you can use the default TableViewModelRenderer.

The important piece is the override of GetViewForHeader. We override this in order to create a custom label that can use the properties and styles we need!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Xamarin.Forms Borderless Entry

Here’s a quick freebee. If you want to create an entry that has no border, it can be done with a pretty simple custom renderer.

Let’s first create a new control that inherits Entry:

BorderlessEntry.cs

 public partial class BorderlessEntry : Entry
    {
        public BorderlessEntry()
        {
            InitializeComponent();
        }
    }

We aren’t doing any special logic or anything here since all we need to do is remove the border.

Now let’s create our renderer on Android:

BorderlessEntryRenderer.cs


[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
namespace YOUR_NAMESPACE
{
    public class BorderlessEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            if (e.OldElement == null)
            {
                Control.Background = null;
            }
        }
    }
}

Note that setting the background drawable to null will kill the border (including the bottom line in AppCompt).

Now let’s create our renderer on iOS:

BorderlessEntryRenderer.cs

[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
namespace YOUR_NAMESPACE
{
    public class BorderlessEntryRenderer : EntryRenderer
    {
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            
            Control.Layer.BorderWidth = 0;
            Control.BorderStyle = UITextBorderStyle.None;
        }
    }
}

The main property here is the BorderStyle.

Lastly, UWP (this should also be the same thing for WP and Win8):

BorderlessEntryRenderer.cs

[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
namespace YOUR_NAMESPACE
{
    public class BorderlessEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control.BorderThickness = new Thickness(0);
            }
        }
    }
}

That’s all there is to it!

Xamarin.Controls – MarkdownTextView

Markdown is cool, and we as developers are seeing more and more of it all around us; documentation, chat, or even just trying to store dynamic displayed strings without storing the crazy extra characters of xml or html.

Markdown is used by parsing it through a series of Regex comparisons and outputting the html equivalent of what is to be displayed. In web, that’s awesome! Parse the markdown, dump it in the DOM. Bam.

But what about native mobile development? I’ve seen solutions out there where people just create a WebView on their platform, and dump the parsed html from the markdown string into that WebView. It might get the job done in a simple scenario, but WebViews are hefty and really should be avoided.

I’ve created a free and open sourced solution to this problem – The MarkdownTextView.

Here’s the repo: https://github.com/SuavePirate/MarkdownTextView

This is a Xamarin.Forms control that renders on iOS and Android. It consumes a string through the Markdown property, and then the custom render on the respective platform renders it out via a UILabel on iOS and a TextView on Android.

Using the MarkdownTextView

To use the control, clone the repository and reference the library projects in your application. Reference the PCL in your PCL or Shared Library, and reference the native library with the renderer in your platform specific project.

In your platform projects, be sure to call:


MarkdownTextView.Init();

Then use the control in either your XAML or your C# page/view:


<ContentPage ...
xmlns:spcontrols="clr-namespace:SPControls.Forms;assembly=SPControls.MarkdownTextView"
...>
<spcontrols:MarkdownTextView Markdown="{Binding MarkdownString}" />
</ContentPage>

var mdTextView = new MarkdownTextView();
mdTextView.Markdown = "# this is my *header* tag";

How It Works

There are five core steps to how the control works:

  1. The Xamarin.Forms control takes the string value from the Markdown property
  2. The Native custom renderer gets the updated string
  3. The native control calls the PCL Markdown class to parse the string into an html string (with some extra clean up)
  4. The native library parses the html string into a platform specific attributed string that the control can render.
    1. iOS: NSAttributedString
    2. Android: ICharSequence
  5. The native renderer then renders the value from the above type into the native control.
    1. iOS: UILabel.AttributedText
    2. Android: TextView.TextFormatted

There are a few smaller steps specific to the platform to handle some tags that are not normally built in, but that’s the basics.

In a follow-up blog post, I will talk about the details of how this is accomplished for each platform, and how to take this outside Xamarin.Forms to use in your native Xamarin applications.

Xamarin.Controls – JsonTextView

I had a relatively unique requirement where we needed to list out items in a single list that were originated from Json. That’s obviously pretty straightforward. However, each of these items coming back as Json had DRASTICALLY different properties.

The go-to thought is to use different DataTemplates for each unique type that was coming back. However, there was no consistency on top of around 100 different types we were going to get. This sounds like a design flaw in what is coming down from the server, but we didn’t have control over that.

I put my solution up on GitHub as a reusable control: https://github.com/SuavePirate/JsonTextView

It’s simply a control for Xamarin.Forms that has a bindable property called Json that consumes a Json string. It then takes that Json and puts it into an organized Label using Span classes:

public void SetJson(string json)
{
    try
    {
        var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
        foreach (var pair in dict)
        {
            var boldSpan = new Span()
            {
                Text = UpperCase ? $"{pair.Key.SplitCamelCase().ToTitleCase()}: " : $"{pair.Key.SplitCamelCase()}: ",
                FontAttributes = FontAttributes.Bold
            };
            var detailSpan = new Span()
            {
                Text = pair.Value.SplitCamelCase().ToTitleCase()
            };
            var lineBreak = new Span()
            {
                Text = "\n"
            };
            FormattedText.Spans.Add(boldSpan);
            FormattedText.Spans.Add(detailSpan);
            FormattedText.Spans.Add(lineBreak);
        }
    }
    catch
    {
        WriteLine("Failed to parse json.");
    }
}

This also uses two extension methodsthat come in handy:

public static string SplitCamelCase(this string str)
{
    return Regex.Replace(
       Regex.Replace(
            str,
            @"(\P{Ll})(\P{Ll}\p{Ll})",
            "$1 $2"
        ),
        @"(\p{Ll})(\P{Ll})",
        "$1 $2"
     );
}

public static string ToTitleCase(this string str)
{
    return string.Join(" ", str.Split(' ').Select(i => $"{i.Substring(0, 1).ToUpper()}{i.Substring(1).ToLower()}").ToArray());
}

The usage is then pretty simple:

XAML


<ContentPage
  ...
  xmlns:sp="clr-namespace:SPControls;assembly=SPControls"
  ...>
    <Grid>
      <sp:JsonTextView Json="{Binding JsonString}" />
    </Grid>
</ContentPage>

Or in C#

...
var jsonTextView = new SPControls.JsonTextView();
jsonTextView.Json = jsonString;
...

Check out the repository for the full code, and help contribute! Fork the repository, add what features you’d like to see, then submit a pull request.

Xamarin.Tips – Super Simple Sqlite

Thinking about locally storing data and entity structures can be intimidating. You might have a complex data structure in your backend server structure and are trying to match that type of data in your mobile apps. Perhaps you’ve just never done it before and need a solution quickly. You might be over thinking it!

Let’s break it down into some straightforward steps.

  1. Create a Xamarin PCL or Shared project. It doesn’t matter if it’s Xamarin.Forms or native.
  2. Install this nuget package in your PCL or Shared project: https://www.nuget.org/packages/sqlite-net-pcl/
  3. Install the same nuget package in your Android, iOS, UWP, and any other project.
  4. Create your model in your PCL or Shared project. In this case, we will use a basic example model:
    public class Profile
    {
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Handle { get; set; }
        public DateTime CreatedDate { get; set; }
    }
    
  5. Create a DbContext class in your PCL or Shared project:
    public class DbContext
    {
        public static string LocalFilePath; // Set this before creating from platform project
        public SQLiteAsyncConnection Database { get; }
        /// <summary>
        /// Initialized a new DbContext
        /// </summary>
        public DbContext()
        {
            Database = new SQLiteAsyncConnection(LocalFilePath + "localdb.db3");
        }
    
        /// <summary>
        /// Creates a table for a given type in sql lite
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<CreateTablesResult> CreateTableAsync<T>() where T : new()
        {
        return await Database.CreateTableAsync<T>();
        }
    
        /// <summary>
        /// Gets a table by it's type from the db.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public AsyncTableQuery<T> Set<T>() where T : new()
        {
            return Database.Table<T>();
        }
    }
    
  6. Create a GenericRepository Class:
    public class GenericSqliteRepository<T> : IGenericRepository<T> where T : new()
    {
        protected readonly DbContext _context;
        public GenericSqliteRepository(DbContext context)
        {
            _context = context;
        }
        public virtual async Task InitializeAsync()
        {
            await _context.CreateTableAsync<T>();
        }
        public virtual async Task AddAsync(T entity)
        {
            await _context.Database.InsertOrReplaceAsync(entity);
        }
        public virtual async Task AddRangeAsync(IEnumerable<T> entities)
        {
            await _context.Database.InsertAllAsync(entities);
        }
    
        public virtual async Task<T> FindAsync(Expression<Func<T, bool>> predicate)
        {
            return await _context.Set<T>().Where(predicate).FirstOrDefaultAsync();
        }
    
        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> predicate)
        {
            return await _context.Set<T>().Where(predicate).ToListAsync();
        }
    
        public virtual async Task<IEnumerable<T>> GetAsync(int skip, int take)
        {
            return await _context.Set<T>().Skip(skip).Take(take).ToListAsync();
        }
    
        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> predicate, int skip, int take)
        {
            return await _context.Set<T>().Where(predicate).Skip(skip).Take(take).ToListAsync();
        }
    
        public virtual async Task RemoveAsync(T entity)
        {
            await _context.Database.DeleteAsync(entity);
        }
    
        public virtual async Task UpdateAsync(T entity)
        {
            await _context.Database.UpdateAsync(entity);
        }
    }
    
  7. Create a ProfileRepository Class:
    public class ProfileRepository : GenericSqliteRepository<Post>
    {
        public ProfileRepository(DbContext context) : base(context)
        {
        }
    }
    
  8. Set your file path in your platform code:
    1. Android
      DbContext.LocalFilePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
      
    2. iOS
      var docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
      string libFolder = Path.Combine(docFolder, "..", "Library", "Databases");
      
      if (!Directory.Exists(libFolder))
      {
          Directory.CreateDirectory(libFolder);
      }
      DbContext.LocalFilePath = libFolder;
      
  9. Use your repository in your shared code or platform code or wherever you want.
    var repo = new ProfileRepository(new DbContext());
    await repo.InitializeAsync();
    ...
    await repo.AddAsync(new Profile {...});
    ...
    var profiles = await repo.GetAsync(0, 10);
    ...
    var profile = await repo.FindAsync(p => p.Id == "foo");
    ...
    
  10. Start storing your things!

This is obviously a simple situation that doesn’t cover all needs, but it’s a place to start for complex data models. Build repositories for each of your types. Control your queries that are very specific in those model-specific repositories.

Look out for a follow up post about some patterns and tips to use for complex and large data sets!

Xamarin.Tips – Create a Bindable Picker in Xamarin.Forms

EDIT: I forgot to mention, but there was a Pull Request approved and added to the Xamarin.Forms repository that is currently available in Xamarin.Forms v2.3.4-pre1 and should release with the next major update. https://developer.xamarin.com/releases/xamarin-forms/xamarin-forms-2.3/2.3.4-pre1/

It’s unfortunate that Xamarin.Forms’ Picker does not ship with any ability to bind the options. To get around this, we can create a pretty simple control: The BindablePicker

public partial class BindablePicker : Picker
{
    public BindablePicker()
    {
    InitializeComponent();
    this.SelectedIndexChanged += OnSelectedIndexChanged;
    }

    public static BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(BindablePicker), default(IEnumerable), propertyChanged: OnItemsSourceChanged);

    public static BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(object), typeof(BindablePicker), default(object), propertyChanged: OnSelectedItemChanged);
    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    private static void OnItemsSourceChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var picker = bindable as BindablePicker;
        picker.Items.Clear();
        if (newvalue != null)
        {

            foreach (var item in (IEnumerable)newvalue)
            {
                picker.Items.Add(item.ToString());
            }
        }

        // TODO: Add more methods for removing items here
    }

    private void OnSelectedIndexChanged(object sender, EventArgs eventArgs)
    {
        if (SelectedIndex &lt; 0 || SelectedIndex &gt; Items.Count - 1)
        {
            SelectedItem = null;
        }
        else
        {
            SelectedItem = Items[SelectedIndex];
        }
    }
    private static void OnSelectedItemChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var picker = bindable as BindablePicker;
        if (newvalue != null)
        {
            picker.SelectedIndex = picker.Items.IndexOf(newvalue.ToString());
        }
    }
}

Then you can use the picker in your XAML like so:

<views:BindablePicker ItemsSource="{Binding TypeList}" Title="Type" SelectedItem="{Binding CurrentType}"/>;

intellitect.com also has a great post on how to do something similar to allow for an enum to be bound to the options.

[Video] Xamarin.Flux

Learn how to use the Flux design pattern with Xamarin.

Source code: https://github.com/SuavePirate/Xamarin.Flux