Tag Archives: Modal Page

A MVVM-styled Service for my Await-able Custom Input Dialogs (XFCustomInputAlertDialog)

So a lot of folks asked me regarding my previous post, An Await-able Transparent, Custom, Popup Input Dialog in Xamarin.Forms! 😉 how they could implement this awesomeness in a MVVM-friendly manner in Xamarin.Forms, instead of having to deal with dirty code-behind ugliness.

Frankly I did the above original implementation in a MVVM-manner, given myself being a MVVM-practitioner, but since there are a lot of newbie Xamarin devs out there, I thought it would help if I push it out there in the simplest manner for the newbies to understand without a hassle.

Anyhow in order to do some justice for the Xamarin-Forms-MVVM practitioners out there, including myself 😉 here I am pushing out how to implement the same awesomeness in Xamarin-Forms MVVM environment in a beautiful code manner! 😀 ❤

Service FTW!

When it comes to dealing with MVVM environments, Services are crucial, which is what we’re going to leverage our previous implementation to.

So we could call up this service from anywhere across our shared code.

This demonstration…

We shall be using Prism as the MVVM framework for this demo Xamarin.Forms project because its awesome! 😉

And create a Service implementation for our XFCustomInputAlertDialog, which we’ll be register with the Prism’s default IoC container.

Rest is pure magic! lol 😉

PS: I shall not be spoon feeding from this post about MVVM or how to set up MVVM framework in Xamarin.Forms, I shall assume you have solid knowledge on MVVM based Xamarin.Forms implementations. 🙂

If you want to be ahead of all, you can grab the Github code from here: https://github.com/UdaraAlwis/XFInputAlertDialogService

Yep this time I’ve created a separate repo for the project. Alright then let’s get started!

Let’s do it…

Taking a step by step approach…

1. Prism MVVM Setup

Add Prism for Xamarin.Forms to your project and do the primarily set up for Prism MVVM framework. (if you’re unaware of how to do this, there’s plenty of tutorials and blog posts online about setting up Prism for Xamarin.Forms)

This also means you’re to set up the Views and ViewModels for the Project. (ex: MainPage -> MainPageViewModel).

2. Set up XFCustomInputAlertDialog basics

There’s few basic things you need to set up from my previous post as follows, and you can go back take a look at that post for these steps,  An Await-able Transparent, Custom, Popup Input Dialog in Xamarin.Forms! 😉

  • Setting up Rg.Plugins.Popup library
  • Create InputAlertDialogBase control
  • Create your Custom Input Views as you wish
  • Manage code-behind of your Custom Input Views

That’s it! nothing more! Alright let’s get started off with leveraging to MVVM!

3. Creating the Service…

So we shall create the service for our Custom Alert Dialogs. We shall call it InputAlertDialogService, thereby start off by creating the interface, IInputAlertDialogService with required methods.

namespace XFInputAlertDialogService.Interfaces
{
    public interface IInputAlertDialogService
    { 
        /// <summary>
        /// Open Text Input Alert Dialog
        /// </summary>
        /// <param name="titleText"></param>
        /// <param name="placeHolderText"></param>
        /// <param name="closeButtonText"></param>
        /// <param name="validationLabelText"></param>
        /// <returns></returns>
        Task<string> OpenTextInputAlertDialog(
            string titleText, string placeHolderText,
            string closeButtonText, string validationLabelText);
			
	
	//add other types of dialog open methods from here..
	// Task<string> OpenCancellableTextInputAlertDialog(...)
	// Task<string> OpenSelectableInputAlertDialog(...)
	// ...
	// ...
    }
}

 

You can add any amount of Service method calls to the interface which you can use to implement the concrete implementation.

github.com/XFInputAlertDialogService/…/Interfaces/IInputAlertDialogService.cs

Next let’s create the concrete implementation of our service, InputAlertDialogService.

namespace XFInputAlertDialogService.Services
{
    public class InputAlertDialogService : IInputAlertDialogService
    {
        public async Task<string> OpenTextInputAlertDialog(
            string titleText, string placeHolderText,
            string closeButtonText, string validationLabelText)
        {
            // create the TextInputView
            var inputView = 
               new TextInputView(titleText, placeHolderText,
                   closeButtonText, validationLabelText);

            // create the Transparent Popup Page
            // of type string since we need a string return
            var popup = new InputAlertDialogBase<string>(inputView);

            // Add the rest of Popup 
	    // Dialog display code below...
	    // just as in XFCustomInputAlertDialog
	    // ...
        }

        //add other types of dialog open methods from here..
        // ...
    }
}

 

There we are inheriting from our interface and doing the necessary concrete implementation. You will add the Popup Dialog instantiating and pushing to the navigation stack logic as you did in XFCustomInputAlertDialog code. Since its going to be repeated I’m not going to post the same code snippet here.

You can take a quick peak in the Gitub Repo though 😉

github.com/XFInputAlertDialogService/…/Services/InputAlertDialogService.cs

Then we need to register our Service Interface and Concrete implementation in the Prism’s default Unity Container.

namespace XFInputAlertDialogService
{
	public partial class App : PrismApplication
	{
		public App
		(IPlatformInitializer initializer = null) :
		base(initializer) { }

		protected override void RegisterTypes()
		{
			...
			
			// services registration
		    Container.RegisterType<IInputAlertDialogService,
			InputAlertDialogService>();
		}
		
		...
	}
}

 

There you go, the service layer is now ready! 😀

4. Consuming the Service…

Now let’s consume our Custom Popup Dialog Service in the ViewModel. First let’s inject it to the ViewModel and prepare it to be used when you need it.

public class MainPageViewModel 
	: BindableBase, INavigationAware
{
	private readonly 
	IInputAlertDialogService _inputAlertDialogService;
	
	public MainPageViewModel(
	IInputAlertDialogService inputAlertDialogService)
	{
		...
	
		_inputAlertDialogService = inputAlertDialogService;
		
		...
	}

        ...
}

 

Thanks to the IoC pattern, look at that beautiful and clean code. 😉

Now you’re ready to invoke the awesome custom popup dialogs from anywhere in your ViewModel. Let’s do that as the final step, shall we?

var result = await 
	_inputAlertDialogService.OpenTextInputAlertDialog(
	"What's your name?",
	"enter here...", 
	"Ok",
	"Ops! Can't leave this empty!");

 

If you don’t get the hint, you can simply create a Command in your ViewModel and bind that to a Button or something in your View and add the above call to the Command’s execution method as shown below. 😉

public DelegateCommand 
		OpenTextInputAlertDialogCommand { get; set; }

public MainPageViewModel(
	IInputAlertDialogService inputAlertDialogService)

{
	...
	
	OpenTextInputAlertDialogCommand = new DelegateCommand(OpenTextInputAlertDialog);
	
	...
}

private async void OpenTextInputAlertDialog()
{
	var result = await 
		_inputAlertDialogService.OpenTextInputAlertDialog(
		"What's your name?",
		"enter here...", 
		"Ok",
		"Ops! Can't leave this empty!");
}

 

There you go pure MVVM-Xamarin.Forms goodness! 😀

If you’re one of the lazy you can grab the whole code from Github: https://github.com/UdaraAlwis/XFInputAlertDialogService

Well fellas, that’s it!

Enjoy! 😀 Share the love!

-Udara Alwis 😀

Advertisements

An Await-able Transparent, Custom, Popup Input Dialog in Xamarin.Forms! ;)

Imagine you wanted to prompt your user with a popup alert dialog (which is also transparent, because its cool! lol) 😉 asking them to enter some value and you want to await the whole task (make it awaitable) while you’re at it, so the execution will halt until the user enter the value, and then retrieve the user entered value to the point of origin? 😀

And just to add some sugar to it, may be you wanted to customize and decorate the appearance of the input view?

Something like this?

Seems pretty cool yeah! That’s what I’m gonna share today!

Right outta Xamarin.Forms?

Now there’s no way you could do either of those things in that scenario right out of Xamarin.Forms! Nope, not with a Modal Popup, which doesn’t support transparency, and not even with DisplayAlerts or ActionSheets, since the’re not customizable, they don’t allow text input or any kind of custom input view, only multiple button selections.

So how could I do it?

Let me explain fellas!

So for transparency and ultimate flexibility of setting up custom popup views, we are going to use the awesome Rg.Plugins.Popup library for Xamarin.Forms and to make the whole Task awaitable let’s use a TaskCompletionSource (Thank you dot net)! 😉

So the trick here for adding custom input views to the popup page, is by creating our Xamarin.Forms custom views using a ContentView and set them to the Content of popup page.

Alright then time for some coding!

Let the coding begin…

But first, setting up!

First thing first create a Xamarin.Forms PCL project in Visual Studio. 🙂

Then install Rg.Plugins.Popup library for Xamarin.Forms through Nuget Package manager.

I’ve actually written a blog post about Rg.Plugins.Popup in my blog right here: So I created a Popup with Transparent background in Xamarin Forms… 😉

Create the Transparent Popup Page…

Once you’re done with that, let’s create our custom Transparent Popup Page using the Rg.Plugins.Popup we just installed.

Something to keep in mind,

  • We should allow it to use Generic data types as for the return data type. 😀
  • Popup page provides us with many cool features, including Page background click handling and back button press handling, which we will override as of disable page background click to dismissal and disable back button press cancellation.
  • Pass in a View and set it to the PopupPage’s Content property, which we will attach the custom input view we want to use in our popup page.
  • Set the transparency level to 0.4 of alpha value.

Let’s call it InputAlertDialogBase.

/// <summary>
/// The awesome Transparent Popup Page
/// sub-classed from Rg.Plugins.Popup
/// Customized for our usecase with
/// Generic data type support for the result
/// </summary>
/// <typeparam name="T"></typeparam>
public class InputAlertDialogBase<T> : PopupPage
{
	public InputAlertDialogBase(View contentBody)
	{
		Content = contentBody;

		this.BackgroundColor = new Color(0, 0, 0, 0.4);
	}

	// Method for animation child in PopupPage
	// Invoced after custom animation end
	protected override Task OnAppearingAnimationEnd()
	{
		return Content.FadeTo(1);
	}

	// Method for animation child in PopupPage
	// Invoked before custom animation begin
	protected override Task OnDisappearingAnimationBegin()
	{
		return Content.FadeTo(1);
	}

	protected override bool OnBackButtonPressed()
	{
		// Prevent back button pressed action on android
		//return base.OnBackButtonPressed();
		return true;
	}

	// Invoced when background is clicked
	protected override bool OnBackgroundClicked()
	{
		// Prevent background clicked action
		//return base.OnBackgroundClicked();
		return false;
	}
}

 

There you go, over to the next step!

Configure the await-able Task properties…

So let’s create a Task and TaskCompletionSource inside our InputAlertDialogBase, to handle await-ability of our “Transparent, Custom, Popup Input Dialog” as I’ve mentioned in the blog title! 😉

public class InputAlertDialogBase<T> : PopupPage
{
	// the awaitable task
	public Task<T> PageClosedTask { get { return PageClosedTaskCompletionSource.Task; } }

	// the task completion source
	public TaskCompletionSource<T> PageClosedTaskCompletionSource { get; set; }

	public InputAlertDialogBase(View contentBody)
	{
		...

		// init the task completion source
		PageClosedTaskCompletionSource = new System.Threading.Tasks.TaskCompletionSource<T>();

		...
	}

	...
}

 

Note that how we are initializing the TaskCompletionSource in the Constructor.

Alright, now our Transparent Popup is ready. Next we need to construct the Custom Input View, that we are going to pass into the InputAlertDialogBase to display and retrieve data input (text or any kind) from the User. 😀

Create your Custom Input View! 😀

Alright this step is totally up to your desires, you could construct any kind of a Custom Input View to be displayed on top of the InputAlertDialogBase we just created above, and retrieve the User’s inputs.

So for this example, let’s create a simple View with Title Label, Text Entry and Ok button yeah! 😉 Also let’s add a simple validation Label inside it to show up if the User tries to leave the Text Entry empty and hit the ok button to quit.

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
    x:Class="XFCustomInputAlertDialog.InputViews.TextInputView"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <ContentView.Content>
        <StackLayout
            Padding="10"
            BackgroundColor="White"
            HorizontalOptions="CenterAndExpand"
            Spacing="5"
            VerticalOptions="CenterAndExpand">
            <Label
                x:Name="TitleLabel"
                FontSize="Medium"
                Text="Enter the value:" />
            <Label
                x:Name="ValidationLabel"
                FontSize="Micro"
                IsVisible="False"
                Text="You can't leave this field empty!"
                TextColor="Red" />
            <Entry x:Name="InputEntry" Placeholder="Enter Here..." />
            <Button x:Name="CloseButton" Text="Ok">
                <Button.HeightRequest>
                    <OnPlatform x:TypeArguments="x:Double">
                        <On Platform="Android" Value="40" />
                        <On Platform="iOS" Value="30" />
                    </OnPlatform>
                </Button.HeightRequest>
            </Button>
        </StackLayout>
    </ContentView.Content>
</ContentView>

 

As you can see we have created a simple ContentView with a custom Text input view! 😀

Notice that we have explicitly named all the elements and added a button click event, this is to make it easy to set custom textual values to the elements and to handle the OK button’s click event as for the closing of the Popup Page. 🙂

Pretty simple yeah, next let’s handle the back end of this custom View to manage the Textual values, Ok button’s click event and validations.

Let’s manage code-behind of Custom Input View…

Now this is important, if you consider a ContentView, all it’s Child elements are private to it’s class scope, so we can’t observe or interact with any of the property value changes or behaviors from outside of the View.

Therefore we need to create custom properties that will expose those required values and events to the public.

Something to keep in mind here,

  • In order to customize the values displayed in the Child elements of the ContentView (Label,Button, etc..) we should pass in the values to the Constructor and set them to the Child elements there.
  • We should create a public EventHandler to handle the Ok Button’s click event from outside the View and add a public string Propery to expose the text Entry’s value to the public.
  • Subscribe to the Entry’s TextChanged event to reflect the value the public string property.
  • Create a public bindable Boolean property to display or hide Validation label in the ContentView. Or you could handle this internally in the View on the Ok Button’s click event as well, but it would be nice if we could expose the Validations to public so we could handle it outside the View.

public partial class TextInputView : ContentView
{
	// public event handler to expose 
	// the Ok button's click event
	public EventHandler CloseButtonEventHandler { get; set; }

	// public string to expose the 
	// text Entry input's value
	public string TextInputResult { get; set; }

	public TextInputView(string titleText, 
          string placeHolderText, string closeButtonText, 
           string validationLabelText)
	{
		InitializeComponent();

		// update the Element's textual values
		TitleLabel.Text = titleText;
		InputEntry.Placeholder = placeHolderText;
		CloseButton.Text = closeButtonText;
		ValidationLabel.Text = validationLabelText;

		// handling events to expose to public
		CloseButton.Clicked += CloseButton_Clicked;
		InputEntry.TextChanged += InputEntry_TextChanged;
	}

	private void CloseButton_Clicked(object sender, EventArgs e)
	{
		// invoke the event handler if its being subscribed
		CloseButtonEventHandler?.Invoke(this, e);
	}

	private void InputEntry_TextChanged(object sender,
					TextChangedEventArgs e)
	{
		// update the public string value 
		// accordingly to the text Entry's value
		TextInputResult = InputEntry.Text;
	}
}

 

So you can see we are passing in all the required values to set to our Child element’s we are passing in to the Constructor and setting them up there. Also we are subscribing to the Ok Button’s OnClick event and text Entry’s TextChanged event.

Inside the CloseButton_Clicked() event we are invoking the public EventHandler CloseButtonEventHandler if it’s being subscribed to by outside.

As well as  the Entry’s InputEntry_TextChanged() event we are updating the public TextInputResult to reflect the Entry’s text value to the public.

Don’t forget to handle Validations…

Oh and here’s the Bindable Boolean property you should include inside the TextInputView code behind to handle the Validations from outside the View.

public partial class TextInputView : ContentView
{
	...
	
	public static readonly BindableProperty 
           IsValidationLabelVisibleProperty =
		BindableProperty.Create(
			nameof(IsValidationLabelVisible),
			typeof(bool),
			typeof(TextInputView),
			false, BindingMode.OneWay, null,
			(bindable, value, newValue) =>
			{
				if ((bool)newValue)
				{
					  
		((TextInputView)bindable).ValidationLabel
					 .IsVisible = true;
				}
				else
				{
					 
		((TextInputView)bindable).ValidationLabel
					.IsVisible = false;
				}
			});

	/// <summary>
	/// Gets or Sets if the ValidationLabel is visible
	/// </summary>
	public bool IsValidationLabelVisible
	{
		get
		{
			return (bool)GetValue(
                             IsValidationLabelVisibleProperty);
		}
		set
		{
			SetValue(
                         IsValidationLabelVisibleProperty, value);
		}
	}
	
	...
}

 

Now speaking of the bindable IsValidationLabelVisibleProperty, we are updating the Validation Label’s visibility based on its value changes accordingly. 🙂

Following this method, you can create any kind of custom Input Views to be attached to our Transparent Popup Page. 🙂 All you need to do is expose the required Values and Events to the public.

Alright next step…

Time to assemble everything and consume it!

Now we are going to put everything together and get it to be used as our “awaitable Transparent, Custom, Popup Input Dialog”! 😉

Somethings to keep in mind here,

  • We need to initialize our TextInputView by passing in the parameters we would like the necessary child elements to display
  • Create an InputAlertDialogBase<string>(), yes of type string, since we are going to return a string from the Popup Alert.
  •  Subscribe to the CloseButtonEventHandler of TextInputView’s instance to handle validation and reflect the Text input value to the TaskCompletionSource.
  • Push the popup page instance to Navigation Stack and await the page’s Task
  • Upon result retrieval Pop the page from Stack and return the user inserted value.

Alright let’s do it…

private async Task<string> LaunchTextInputPopup()
{
	// create the TextInputView
	var inputView = new TextInputView(
		"What's your name?", "enter here...", 
		"Ok", "Ops! Can't leave this empty!");

	// create the Transparent Popup Page
	// of type string since we need a string return
	var popup = new InputAlertDialogBase<string>(inputView);

	// subscribe to the TextInputView's Button click event
	inputView.CloseButtonEventHandler +=
		(sender, obj) =>
		{
			if (!string.IsNullOrEmpty(
                         ((TextInputView)sender).TextInputResult))
			{
				
                            ((TextInputView)sender)
                               .IsValidationLabelVisible = false;
				
                            // update the page completion source
                            popup.PageClosedTaskCompletionSource
                                .SetResult(
                                ((TextInputView)sender)
                                      .TextInputResult);
			}
			else
			{
				
                             ((TextInputView)sender)
                                 .IsValidationLabelVisible = true;
			}
		};

	// Push the page to Navigation Stack
	await PopupNavigation.PushAsync(popup);

	// await for the user to enter the text input
	var result = await popup.PageClosedTask;

	// Pop the page from Navigation Stack
	await PopupNavigation.PopAsync();

	// return user inserted text value
	return result;
}

 

There you go, step by step as I explained before you can see how it’s being consumed. Specially inside the CloseButtonEventHandler, every time the event fires we are checking the TextInputResult property and enabling or disabling the IsValidationLabelVisible property, as well as updating the PageClosedTaskCompletionSource property value if a text value is being entered by the User, which will in return update the awaiting PageClosedTask and task will proceed to completion state, then return the value after popping the Page. 😀

There you go! 😀 How straight forward is that! 😉

Keep in mind like I said before you can add any kind of a customized View on top of our Transparent Popup Page, and retrieve any kind of result as you expect from the User following the same steps. 😀

Let’s see this in action…

 

Look at that coolness right! 😉

Since it’s full on Xamarin.Forms, and doesn’t have a single line of native code, you could straight up run this implementation on all Android, iOS, UWP, WinPhone as you wish! 😀

I want more! 😮

Alright now that’s just a little bit of basic head start of what you could do, whereas if you get creative and smart you could do a lot more cool stuff like this…

  

 

 

There you have it, some cool stuff I played around with my implementation. 😉

You can grab the Github code from here: github.com/UdaraAlwis/XFCustomInputAlertDialog

Well fellas, that’s it for now!

Enjoy! 😀 Share the love!

-Udara Alwis 😀