Create “Press back again to exit” toast on Xamarin Androd

I found this relatively simple to implement.

AndroidToast

In the Activity that represents the final view of your application, i.e. the one that you want the user to see the Toast popup message, add this override code:

private double _backPressTime = 0;

public override void OnBackPressed()
{
	double t = new TimeSpan(DateTime.Now.Ticks).TotalMilliseconds;

	if (t - _backPressTime > 2000) // i.e. 2000 milliseconds
	{
		_backPressTime = t;
		Toast.MakeText(this, "Press back again to exit", ToastLength.Short)
				.Show();
	}
	else
	{
		base.OnBackPressed(); // now we can quit
	}
}

WPF Switch Color Theme at Runtime

This very simple class will allow you to switch Themes in a WPF application. Its not the only way to do it and is not a MVVM implementation, but can be modified easily if needed.

Here is the resource (theme) switching code:

public static class ThemeHelper
{
	public static void SwitchTheme(string stylefile)
	{
		if (File.Exists(stylefile))
		{
			using (FileStream fs = new FileStream(stylefile, FileMode.Open))
			{
				ResourceDictionary dic = (ResourceDictionary) XamlReader.Load(fs);
				Application.Current.Resources.MergedDictionaries.Clear();
				Application.Current.Resources.MergedDictionaries.Add(dic);
			}
		}   
	}

	public static void SwitchTheme(Uri themeUri)
	{
		var theme = new ResourceDictionary();
		theme.Source = themeUri;
		Application.Current.Resources.MergedDictionaries.Clear();            
		Application.Current.Resources.MergedDictionaries.Add(theme);
	}
}

For this to work just create a folder called “Themes” add your Theme files into there and mark as content. Each theme file must be in the same structure (i.e. use the same Key names obviously) for this to work.

Here is an example of a theme file:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="ThemeColor1">Green</SolidColorBrush>
    <SolidColorBrush x:Key="ThemeColor2">Red</SolidColorBrush>
    <SolidColorBrush x:Key="ThemeColor3">Orange</SolidColorBrush>
</ResourceDictionary>

Then anywhere in code you can changes themes like so (assuming you added a file called MangoTheme.xaml into the \Themes\ directory:

ThemeHelper.SwitchTheme(new Uri("/Themes/MangoTheme.xaml", UriKind.Relative));

Make sure you use DynamicResource markup extension in your bindings for anything that could change during runtime, i.e.

Background="{DynamicResource ThemeColor1}"

Generic Storage Manager

All of my apps make use of a common class for data storage management. Its simple and works for my needs, even providing a way to create a default context if one does not already exist.

Obviously any type you want to use with this must be decorated with the DataContractAttribute.

class StorageManager<T> where T : class 
{
	private readonly string _filename;
	private readonly Func<T> _defCtxFunc;
	
	public StorageManager(string filename, Func<T> defaultContextCreation)
	{
		_filename = filename;
		_defCtxFunc = defaultContextCreation;
	}
	
	public async Task<T> Load(Func<T> defaultContextCreation)
	{
		object existingData = null;

		try
		{
			var serializer = new DataContractSerializer(typeof (T));
			using (
				var stream =
					await
						ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(_filename))

			{
				existingData = serializer.ReadObject(stream);
				stream.Flush();
			}
		}
		catch (Exception e)
		{
			Debug.WriteLine("StorageManager.Load({1}) failed with exception :: {0}", _filename, e);
		}

		return (existingData ?? defaultContextCreation.Invoke()) as T;
	}

	public async Task<bool> Save(T data)
	{
		try
		{
			var serializer = new DataContractSerializer(typeof (T));
			using (
				var stream =
					await
						ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(_filename,
							CreationCollisionOption.ReplaceExisting))
			{
				serializer.WriteObject(stream, data);
				stream.Flush();                    
			}

			Debug.WriteLine("Save [{0}] to [{1}] success", _filename, ApplicationData.Current.LocalFolder.Path);
			return true;
		}
		catch(Exception e)
		{
			Debug.WriteLine("Save [{0}] failed with exception :: {1}", _filename, e);
			return false;
		}
	}
}