Commands are cool, but man they’re repetitive…

By | July 10, 2012

Using WPF/XAML databinding any good programmer comes along Commanding. It’s the thing you’re supposed to do instead of adding an EventHandler to the Click event of your button.

But Christ, adding Commands everywhere gets to be damn repetitive.

Enter awesomeness.

	public class GenericCommand : ICommand
	{
		Action<object> _command;
		Func<object, bool> _canExecuteCheck;
		public GenericCommand(Action<object> execute, Func<object, bool> canExecute = null)
		{
			_command = execute;
			_canExecuteCheck = canExecute;
		}
		#region ICommand Members

		public bool CanExecute(object parameter)
		{
			if (_canExecuteCheck != null)
			{
				return _canExecuteCheck(parameter);
			}

			return true;
		}

		public event EventHandler CanExecuteChanged;

		public void Execute(object parameter)
		{
			_command(parameter);
		}

		#endregion
	}

Now, normally I hate using ‘object’ as a parameter to things, especially when it means you’ll be unboxing w/in the function, but in this case I don’t care. I hate having to remember how to write a Command every time I need one.
Speaking of which, a somewhat common thing to do in Windows Phone is click a control and crack off IE to load a URL, especially on the “About” page. Enter more awesomeness:

	public class LaunchWebLinkCommand : ICommand
	{
		private string _predefinedUrl;
		public LaunchWebLinkCommand(string predefinedUrl)
		{
			_predefinedUrl = predefinedUrl;
		}
		#region ICommand Members

		public bool CanExecute(object parameter)
		{
			return !string.IsNullOrWhiteSpace(_predefinedUrl) || !string.IsNullOrWhiteSpace(parameter as string);
		}

		public event System.EventHandler CanExecuteChanged;

		public void Execute(object parameter)
		{
			var site = parameter as string;
			try
			{
				if (!string.IsNullOrWhiteSpace(site))
				{
					new Microsoft.Phone.Tasks.WebBrowserTask { Uri = new System.Uri(site) }.Show();
				}
				else
				{
					new Microsoft.Phone.Tasks.WebBrowserTask { Uri = new System.Uri(_predefinedUrl) }.Show();
				}
			}
			catch
			{	// Swallow any exceptions, happen as a result of a user multi-click before task fires
			}
		}

		#endregion
	}

Usage looks like:
(CodeBehind)

		public ICommand TranslationLinkClicked
		{
			get
			{
				return new LaunchWebLinkCommand("http://.......");
			}
		}

(XAML)

<HyperlinkButton Content="click here" Command="{Binding TranslationLinkClicked}" />

Y’know what else is cool? Deep linking tiles in to your app. You should be doing it.

	public class PinToStartCommand : ICommand
	{
		private string _deepLink;
		private ShellTileData _tileData;
		public PinToStartCommand(string deepLink, ShellTileData tileData)
		{
			_deepLink = deepLink;
			_tileData = tileData;
		}

		#region ICommand Members

		public bool CanExecute(object parameter)
		{
			// can only pin to start if it hasn't already been pinned
			return !ShellTile.ActiveTiles.Any(t => t.NavigationUri.ToString().Contains(_deepLink));
		}

		public event EventHandler CanExecuteChanged;

		public void Execute(object parameter)
		{
			ShellTile.Create(new Uri(_deepLink, UriKind.Relative), _tileData);
		}

		#endregion
	}

Tune in next time where I make it rain XAML Converters!

  • A little note: always put a try/catch around WebBrowserTask or launchers. They are slow to execute and in some case, you can click twice on a button and a crash occurs.

    • Brandon

      another good tip, thanks!