Xamarin.Tip – Borderless Inputs

I published multiple posts this week about creating Xamarin.Forms controls without borders using Custom renderers. This post is your one stop shop for all these posts. These are the controls that are used in my repository to create Material Design inputs in Xamarin.Forms that you can find here:
https://github.com/SuavePirate/SuaveControls.MaterialFormControls. These will be talked about in posts to come!
Check the borderless controls out here:

  1. Xamarin.Forms Borderless Entry
  2. Xamarin.Forms Borderless Picker
  3. Xamarin.Forms Borderless DatePicker
  4. Xamarin.Forms Borderless TimePicker
  5. Xamarin.Forms Borderless Editor

And check out how they look here:

BorderlessEntry


BorderlessEditor

BorderlessPicker

BorderlessDatePicker

BorderlessTimePicker

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!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisements

Xamarin.Tip – Mvvm Light and Dependency Injection

Inversion of Control and Dependency Injection are some design principles that help make our applications more flexible and scalable. They both help us separate our implementations and make it easy to substitute drastic changes to our implemented data or business logic whether it be for writing unit tests or product improvement.

Xamarin is a platform where IoC and DI fit extremely well. I’ve talked about this concept a few other times in both my blogs and videos about the Onion Architecture in Xamarin as well as how to call Platform Specific code from a Portable Class Library. You can find those posts and videos here:

  1. Onionizing Xamarin Part 6
  2. [VIDEO] Xamarin.Tips: Calling Platform-Specific Code from a PCL (Dependency Injection)

In this post, I want to talk about using DI with Mvvm Light at a VERY basic level.

First, let’s define an interface for a service we might use:

IUserService.cs

public interface IUserService
{
    Task<User> GetCurrentUserAsync();
}

Now let’s create two different implementations. One that will be the service used in the application and the other that will be used for testing.

UserService.cs

public class UserService : IUserService
{
    // makes a call to a web api to get a user
    public async Task<User> GetCurrentUserAsync()
    {
        using (var client = new HttpClient())
        {
            var response = await client.GetAsync("https://mywebapi.mydomain/api/currentuser");
            var content = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<User>(content);
        }
    }
}

TestUserServices.cs

public class TestUserService : IUserService
{
    public Task<User> GetCurrentUserAsync()
    {
        return Task.FromResult(new User { Name = "Test User" });
    }
}

Now we need a ViewModel that will use this service. We define a private readonly IUserService and then inject the implementation that we want in the constructor of the ViewModel.

CurrentUserViewModel.cs

public class CurrentUserViewModel : ViewModelBase
{
    // use the interface as the service and inject the implementation in the constructur
    private readonly IUserService _userService;
    private User _user;

    public User User
    {
        get
        {
            return _user;
        }
        set
        {
            Set(ref _user, value);
        }
    }

    public CurrentUserViewModel(IUserService userService)
    {
        _userService = userService;
    }

    public async Task UpdateUserAsync()
    {
        User = await _userService.GetCurrentUserAsync();
    }
}

Now let’s define an IoCConfig that handles registering dependencies and implementations.

IoCConfig.cs

public class IoCConfig
{
    public IoCConfig()
    {
        // use SimpleIoc from MvvmLight as our locator provider
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    }

    // register the real implementation
    public void RegisterServices()
    {
        SimpleIoc.Default.Register<IUserService, UserService>();
    }

    // register the test implementation
    public void RegisterTestServices()
    {
        SimpleIoc.Default.Register<IUserService, TestUserService>();
    }

    // register the view model
    public void RegisterViewModels()
    {
        SimpleIoc.Default.Register<CurrentUserViewModel>();
    }
}

Now that we can register our Services as well as our ViewModels, the dependency resolver from SimpleIoc can retrieve an instance of CurrentUserViewModel with whichever version of IUserService is registered depending on whether we call RegisterServices or RegisterTestServices.

Now we can retrieve our instance of the CurrentUserViewModel by calling

var currentUserViewModel = ServiceLocator.Current.GetInstance<CurrentUserViewModel>();

MvvmLight recommends using a ViewModelLocator to get the instance of your ViewModels:

ViewModelLocator.cs

public class ViewModelLocator
{
    private readonly IoCConfig _iocConfig;
    public CurrentUserViewModel CurrentUser
    {
        get
        {
            return ServiceLocator.Current.GetInstance<CurrentUserViewModel>();
        }
    }

    public ViewModelLocator()
    {
        _iocConfig = new IoCConfig();
        _iocConfig.RegisterServices();
        //_iocConfig.RegisterTestServices();
        _iocConfig.RegisterViewModels();
    }

}

It’s recommended to either create your ViewModelLocator at the app start up, or if you’re using Xamarin.Forms, register it as a Resource in your App.xaml

<Application ...     xmlns:locator="clr-namespace:YOUR_LOCATOR_LOCATION">
    <Application.Resources>
        <ResourceDictionary>
            <locator:ViewModelLocator x:Key="Locator"/>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Now in your XAML pages, you can automatically wire up your view model.

MainPage.xaml

<ContentPage ...     BindingContext="{Binding Source={StaticResource Locator}, Path=CurrentUser}"     Title="{Binding User.Name}">
...
</ContentPage>

In order to change to your testing data, you can just switch which call to your IoCConfig is made for registering your dependency without having to make any changes to any of your other layers or UI!

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!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – Adding Dynamic Elevation to Your Xamarin.Forms Buttons

Before Reading

In a previous post, I talked about bringing Material Design to your iOS applications in Xamarin.Forms and adding drop shadows to them. You might want to read that here first: Xamarin.Tips – Creating a Material Design Button in iOS

In another post, we learned how to override the Android Button Elevations. We will be doing this in this post in order to set a dynamic elevation. You can read that here: Xamarin.Tips – Overriding Android Button Shadows/Elevation

Now in this post, we will combine these two concepts with a new custom Xamarin.Forms component called MaterialButton that will have a new Elevation property to control the elevation and shadow of the underlying button control.

The source code and an example can be found here: https://github.com/SuavePirate/MaterialButton

Using the existing code

You can of course use the code I wrote and put on GitHub for this. In order to use it, simply:

  1. Clone the repository at  https://github.com/SuavePirate/MaterialButton
  2. Include all 3 `src` projects in your Solution
  3. Reference the Shared project in all Xamarin.Forms and platform projects
  4. Reference the Android project in your Android projects
  5. Reference the iOS project in your iOS projects
  6. Use the control as below (see example projects to demo)

Reference the control in your XAML:

MainPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"              xmlns:local="clr-namespace:MaterialButtonExample"              xmlns:suave="clr-namespace:SuaveControls.MaterialButton.Shared;assembly=SuaveControls.MaterialButton.Shared"              x:Class="MaterialButtonExample.MainPage">

	<suave:MaterialButton x:Name="MyButton"                            BackgroundColor="#03A9F4"                            TextColor="White"                            Text="Click to raise elevation"                            Elevation="1"                            VerticalOptions="Center"                            HorizontalOptions="Center"                           WidthRequest="300"                           Clicked="MyButton_Clicked"/>

</ContentPage>

MainPage.xaml.cs

namespace MaterialButtonExample
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void MyButton_Clicked(object sender, EventArgs e)
        {
            MyButton.Elevation++;
        }
    }
}

In your iOS AppDelegate you’ll also need to call the Initialize method to ensure that the Custom renderer does not get excluded during linking:

AppDelegate.cs

namespace MaterialButtonExample.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            MaterialButtonRenderer.Initialize();
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }
    }
}

Now you can see your results!

Creating Your Own Material Design Button

First things first, let’s create our new Xamarin.Forms control before we implement our custom renderers:

MaterialButton.cs

namespace SuaveControls.MaterialButton.Shared
{
    public class MaterialButton : Button
    {
        public static BindableProperty ElevationProperty = BindableProperty.Create(nameof(Elevation), typeof(float), typeof(MaterialButton), 4.0f);

        public float Elevation
        {
            get
            {
                return (float)GetValue(ElevationProperty);
            }
            set
            {
                SetValue(ElevationProperty, value);
            }
        }
    }
}

Now let’s implement our iOS and Android custom renderers.

iOS:
MaterialButtonRenderer


[assembly: ExportRenderer(typeof(MaterialButton), typeof(MaterialButtonRenderer))]
namespace SuaveControls.MaterialButton.iOS
{
    public class MaterialButtonRenderer : ButtonRenderer
    {
        public static void Initialize()
        {
            // empty, but used for beating the linker
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement == null)
                return;

        }

        public override void Draw(CGRect rect)
        {
            base.Draw(rect);
            UpdateShadow();
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if(e.PropertyName == "Elevation")
            {
                UpdateShadow();
            }
        }

        private void UpdateShadow()
        {

            var materialButton = (Shared.MaterialButton)Element;

            // Update shadow to match better material design standards of elevation
            Layer.ShadowRadius = materialButton.Elevation;
            Layer.ShadowColor = UIColor.Gray.CGColor;
            Layer.ShadowOffset = new CGSize(2, 2);
            Layer.ShadowOpacity = 0.80f;
            Layer.ShadowPath = UIBezierPath.FromRect(Layer.Bounds).CGPath;
            Layer.MasksToBounds = false;

        }
    }
}

Notice how we use the UpdateShadow method to use the Elevation property to set the ShadowRadius of our UIButton's Layer.

It’s important to also make the UpdateShadow call in the OnElementPropertyChanged so that we can dynamically change the Elevation property in our Xamarin.Forms control and see it reflected in the underlying UIButton.

Now let’s do it on Android:

MaterialButtonRenderer

[assembly: ExportRenderer(typeof(MaterialButton), typeof(MaterialButtonRenderer))]
namespace SuaveControls.MaterialButton.Droid
{
    public class MaterialButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
    {
        ///
<summary>
        /// Set up the elevation from load
        /// </summary>

        /// <param name="e"></param>
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement == null)
                return;

            var materialButton = (Shared.MaterialButton)Element;

            // we need to reset the StateListAnimator to override the setting of Elevation on touch down and release.
            Control.StateListAnimator = new Android.Animation.StateListAnimator();

            // set the elevation manually
            ViewCompat.SetElevation(this, materialButton.Elevation);
            ViewCompat.SetElevation(Control, materialButton.Elevation);
        }

        public override void Draw(Canvas canvas)
        {
            var materialButton = (Shared.MaterialButton)Element;
            Control.Elevation = materialButton.Elevation;
            base.Draw(canvas);
        }

        ///
<summary>
        /// Update the elevation when updated from Xamarin.Forms
        /// </summary>

        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if(e.PropertyName == "Elevation")
            {
                var materialButton = (Shared.MaterialButton)Element;
                ViewCompat.SetElevation(this, materialButton.Elevation);
                ViewCompat.SetElevation(Control, materialButton.Elevation);
                UpdateLayout();
            }
        }
    }
}

Just as mentioned in the iOS implementation, we need to make sure that we implement our changes in both the OnElementChanged method as well as the OnElementPropertyChanged event to ensure we are able to update our Elevation with MVVM.

Now we can use our control in our pages!

MainPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"              xmlns:local="clr-namespace:MaterialButtonExample"              xmlns:suave="clr-namespace:SuaveControls.MaterialButton.Shared;assembly=SuaveControls.MaterialButton.Shared"              x:Class="MaterialButtonExample.MainPage">

	<suave:MaterialButton x:Name="MyButton"                            BackgroundColor="#03A9F4"                            TextColor="White"                            Text="Click to raise elevation"                            Elevation="1"                            VerticalOptions="Center"                            HorizontalOptions="Center"                           WidthRequest="300"                           Clicked="MyButton_Clicked"/>

</ContentPage>

MainPage.xaml.cs

namespace MaterialButtonExample
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void MyButton_Clicked(object sender, EventArgs e)
        {
            MyButton.Elevation++;
        }
    }
}

In your iOS AppDelegate you’ll also need to call the Initialize method to ensure that the Custom renderer does not get excluded during linking:

AppDelegate.cs

namespace MaterialButtonExample.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            MaterialButtonRenderer.Initialize();
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }
    }
}

Now you can see your results!

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!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – MvvmLight Code Snippets for Visual Studio for Mac

I previously made a post about some Mvvm Light shortcuts / code snippets in Visual Studio, but what about Visual Studio for Mac?

Code snippets in Visual Studio for Mac work a little differently, but here is how to add your own:

  1. Go to Visual Studio > Preferences > Text Editor > Code Snippets
  2. Click on the Add button
  3. Set the language for your snippet, the shortcut, and other optional options
  4. Write the template for your snippet
  5. Confirm and use

Here are two easy ones that have made my life easier for a Bindable Property and Relay Command:

propb:

private $type$ $fieldName$;

public $type$ $name$
{
    get
    {
        return $fieldName$;
    }
    set
    {
        Set(() => $name$, ref $fieldName$, value);
    }
}

Screen Shot 2017-05-25 at 4.38.45 PM

rcmd:

private ICommand $fieldName$;

public ICommand $name$ => $fieldName$ ??
    ($fieldName$ = new RelayCommand(() => ));

Screen Shot 2017-05-25 at 4.39.19 PM.png

It’s as easy as that. Now go out there and start writing less code!

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!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – Binding a Picker to an Enum

So a recent Xamarin.Forms update released the new Bindable Picker, which allows you to bind an IList of objects to the picker (which will be ToString()‘ed). However, I’ve often find myself needing to create a form for a model that has enum properties. Previously, in order to do this, I would have to create a custom List or string from my enum and map it manually, then read from the SelectedItem bound to another string property, then when I need the actual value I’d have to map it back to the enum it “represents”.

It might have looked something like this:

MyViewModel.cs

...
private DogBreed _breedEnum; // this is our enum of: BorderCollie, LabradorRetriever, PitBull, etc.

public List<string> BreedNames
{
    get
    {
        return new List<string> { "Border Collie", "Labrador Retriever", "Pit Bull" };
    }
}

private string _selectedBreed;
public string SelectedBreed
{
    get
    {
        return _selectedBreed;
    }
    set
    {
        Set(ref _selectedBreed, value); // this is using MvvmLight
    }
}

public void DoSomethingWithTheBreed()
{
    switch(SelectedBreed)
    {
        case "Border Collie": _breedEnum = DogBreed.BorderCollie;
            break;
        case "Labrador Retriever": _breedEnum = DogBreed.LabradorRetriever;
            break;
        case "Pit Bull": _breedEnum = DogBreed.PitBull;
            break;
        //...
    }

    DoSomething(_breedEnum);
}
...

And our XAML

<Picker ItemsSource="{Binding BreedNames}" SelectedItem="{Binding SelectedBreed}"/>

As you can see, this is pretty gross…

Here’s a quick little strategy I use to make the binding process a little easier with my enums. It’s broken into just 3 quick parts:

  1. Create a extension methods to get a readable string from our `enum`
  2. Create a `Converter` to convert the `SelectedIndex` to the `enum` field
  3. Wire up the fields and XAML

Let’s create our enum extension methods to get a readable string for the UI:
StringExtensions.cs

    public static class StringExtensions
    {
        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"
            );
        }
    }

This SplitCamelCase method will take a string that is camel cased and split it out into separate words such as `”ThisIsMyValue”.SplitCamelCase(); // “This Is My Value”

Now that we have the ability to get a readable string from the enum values, let’s create our ViewModel properties we will need.

MyViewModel.cs

...
private DogBreed _selectedBreed;
public DogBreed SelectedBreed
{
    get
    {
        return _selectedBreed;
    }
    set
    {
        Set(ref _selectedBreed, value);
    }
}

public List<string> BreedNames
{
    get
    {
        return Enum.GetNames(typeof(DogBreed)).Select(b => b.SplitCamelCase()).ToList();
    }
}

public void DoSomethingWithBreed()
{
    DoSomething(SelectedBreed);
}
...

So much cleaner already. Now we need to create a Converter that our XAML can use to actually set the SelectedBreed property of our ViewModel.

IntEnumConverter.cs

    public class IntEnumConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is Enum)
            {
                return (int)value;
            }
            return 0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if(value is int)
            {
                return Enum.ToObject(targetType, value);
            }
            return 0;
        }
    }

Last thing to do is use our IntEnumConverter and our properties to create our view in XAML:

MyView.xaml

<ContentPage.Resources>
    <ResourceDictionary>
        <converters:IntEnumConverter x:Key="IntEnum"/>
    </ResourceDictionary>
</ContentPage.Resources>
<Picker ItemsSource="{Binding BreedNames}" SelectedIndex="{Binding SelectedBreed, Converter=IntEnum}"/>

Here’s what we have!

Now you have the means to bind any of your Pickers quite easily to any of your custom enum fields!

“Woah! How did you get that Material Design Looking Picker on iOS”… Stay tuned!

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!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tips – MVVM Light Set Expressions Explained

I recently published a post about creating some Visual Studio code snippets for shorcutting the overhead of writing bindable properties and commands with MvvmLight. Xamarin.Tips – Visual Studio Code Templates/Snippets for MVVM Light

This post sparked some people who may or may not have used  Mvvm Light in the past to ask me about how it works underneath, and specifically the Set call made. For example:

private string _myText;

public string MyText
{
    get
    {
        return _myText;
    }
    set
    {
        // This is where the questions are.
        Set(() => MyText, ref _myText, value);
    }
}

I figured I would make another post to dissect this and explain what it is and how it is used!


First off, why are we doing this at all? What does this really do for us?

We use MvvmLight in order to create two-way or one-way bindings to our views whether that is in WPF, UWP, or Xamarin.Forms. The way these bindings are handled is by implementing INotifyPropertyChanged. When we implement INotifyPropertyChanged, we create a public event called PropertyChanged. PropertyChanged takes a custom EventArgs that includes the name of the property that was changed as a string. You would invoke that like this:

PropertyChanged?.Invoke(new PropertyChangedEventArgs("MyText"));

We can then have an event handler attached to this:

myViewModel.PropertyChanged += (sender, args) =>
{
    Console.WriteLine(args.PropertyName); // "MyText"
};

However, platforms such as WPF, UWP, and Xamarin give us the ability to use XAML to create these bindings like this (in Xamarin.Forms):

<Label Text="{Binding MyText}"/>

Setting bindings like this creates event handlers in the background if the BindingContext (or DataContext if you’re in UWP/WPF) implements INotifyPropertyChanged.

So now we can create auto-updating views with our bindings and calling PropertyChanged, but that’s a pain to do for every single property. That’s where libraries like MvvmLight come into play. They help handle a lot of the manual calls and ugly code. So now let’s look at what MvvmLight is really doing under the covers.

First, we need to look at the ViewModelBase class that MvvmLight ships and that contains the Set method we are talking about. ViewModelBase inherits from ObservableObject (another class MvvmLight), and ObservableObject is what is implementing INotifyPropertyChanged! We found it!

So how are ViewModelBase.Set and ObservableObject.Set making their way to calling PropertyChanged?

Let’s dissect the three parameters for the Set method used in the templates I created:

Set(() => MyText, ref _myText, value);
  1. The first is of type Expression<Func>. It is an expression that is returning the property that is calling it? This is where the fun stuff is really happening, so more on that later.
  2. The second is the underlying field that needs to be updated, passed in as a reference type rather than by value.
  3. The third is the new value that it is being set to.

The last two seem to make sense right away: what field are we updating, and what is the value we are setting it to? We need to pass the field in as a ref so that when we update it, it updates in the original model that passed it in rather than simply passing the value of the field into the method.

So what is that Expression?

The only thing left in order to call PropertyChanged is the name of the property being updated, so that must be what the property expression is for. Without decompiling the MvvmLight dlls and looking at the source code, we can infer how we might be able to pull the property name out of that Expression.

First, we need to get the Body of the Expression as a System.Linq.Expression.MemberExpression. The MemberExpression has a Member property which we can then pull property info from. We can cast that Member as a System.Reflection.PropertyInfo, and with that PropertyInfo, we can take the name of the property.

Expression<Func<string>> myTextExpression = () => MyText;
var body = myTextExpression.Body as MemberExpression;
var member = body.Member as PropertyInfo;
var finalPropertyName = member.Name; // we have it!

Then the final step is to finally invoke PropertyChanged with that property name.

I do also want to point out that although I use this particular Set method from MvvmLight, the ObservableObject and ViewModelBase do come with multiple overloads of Set that might work better for your preferred practices. For example, you can call Set without the property expression, and just pass the name of the property in directly. For example:

private string _myText;

public string MyText
{
    get
    {
        return _myText;
    }
    set
    {
        Set("MyText", ref _myText, value); 
    }
}

OR to be even more optimized, you can use nameof to get the name of the property without having to have string-literals floating around in your code:

private string _myText;

public string MyText
{
    get
    {
        return _myText;
    }
    set
    {
        Set(nameof(MyText), ref _myText, value); 
    }
}

Here are all the overloads available to use:

ViewModelBase.cs

protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue, bool broadcast);
protected bool Set<T>(string propertyName, ref T field, T newValue = default(T), bool broadcast = false);
protected bool Set<T>(ref T field, T newValue = default(T), bool broadcast = false, [CallerMemberName] string propertyName = null);

ObservableObject.cs

// THIS IS THE ONE WE WERE USING
protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue);
protected bool Set<T>(string propertyName, ref T field, T newValue);
protected bool Set<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null);

If you happen to have any other questions about how this works, or about breaking down Expressions like we did, feel free to drop a comment on this post, or mention me on Twitter @Suave_Pirate.



And as always:



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!

Interested in sponsoring your developer content? Message me on twitter @Suave_Pirate for details.

Xamarin.Tips – Restrict the Length of Your Entry Text

Here’s a quick one on how to restrict the number of characters a user can enter in an Entry. Basically, we are going to create a custom Behavior and then apply it to our Entry.

EntryLengthValidatorBehavior.cs

 /// <summary>
    /// Behavior that restricts the length of an entry
    /// </summary>
    public class EntryLengthValidatorBehavior : Behavior<Entry>
    {
        public int MaxLength { get; set; }

        protected override void OnAttachedTo(Entry bindable)
        {
            base.OnAttachedTo(bindable);
            bindable.TextChanged += OnEntryTextChanged;
        }

        protected override void OnDetachingFrom(Entry bindable)
        {
            base.OnDetachingFrom(bindable);
            bindable.TextChanged -= OnEntryTextChanged;
        }

        void OnEntryTextChanged(object sender, TextChangedEventArgs e)
        {
            var entry = (Entry)sender;

            if (entry.Text.Length > this.MaxLength)
            {
                string entryText = entry.Text;
                entry.TextChanged -= OnEntryTextChanged;
                entry.Text = e.OldTextValue;
                entry.TextChanged += OnEntryTextChanged;
            }
        }
    }

Now we can apply it in our Xaml:

<Entry x:Name="Pin1" TextColor="White">
    <Entry.Behaviors>
        <behaviors:EntryLengthValidatorBehavior MaxLength="4"/>
    </Entry.Behaviors>
</Entry>

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!