Using a Hyperlink in MVVM

Extending the functionality of a control with attached properties

Published on 17 August 2016

The XAML (i.e. WPF, WinRT, UWP family) Hyperlink is a terrific little control (ok, it's not actually a Control - it's a ContentElement - but it does allow interaction hence using the term control here). It follows the current environment's theme such that the user naturally knows it's a link that can be clicked and it can be embedded inside TextBlock elements so that it naturally flows with the other content.

For example:

However, out of the box, this control's functionality is somewhat limited. As standard, it is simply able to perform navigation on any Frame element the control is hosted within. Any other type of behavior requires the developer to subscribe to the control's OnHyperlinkClicked event and perform the required operations from code-behind.

Unfortunately, neither of these approaches work for 'ViewModel First' MVVM, which, after many years employing MVVM is by far my favoured approach.

In a project I've been working on which employs this pattern, a state-machine is used to track application state and each transition between states causing a navigation to be performed in the UI. In one view within the application, there was a desire to instigate a state-machine transition by clicking on a Hyperlink embedded within some text. Ideally, when clicked, the Hyperlink would execute an ICommand instance data-bound to the view from the view-model. Obviously this wasn't possible as standard so I started thinking through alternatives.

My first inclination was to restyle a Button to look like a Hyperlink. This would, ostensibly, be fairly straight forward and naturally provided a Command DependencyProperty to bind to. However, keeping the hyperlink styled as per the current system theme would be arduous to say the least.

Putting this aside, I came across this post which employed an attached property to start a process (normally a browser to display external content) on the host PC. Realising this approach could be extended to accomplish my goals I refactored it to the following:

Which can be used as follows:

Et voil√°, a Hyperlink control which is able to execute a data-bound ICommand instance. Obviously it could be extended further to disable the hyperlink when the command reports execution is disabled (via CanExecuteChanged) and provide a CommandParamter binding for passing additional information through to the command execution, but in a lot of instances - and certainly for me in this scenario - YAGNI.

m.parentNode.insertBefore(a,m) })(window,document,'script','//','ga'); ga('create', 'UA-70151903-1', 'auto'); ga('send', 'pageview'); EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ var disqus_shortname = 'ibebbs'; // required: replace example with your forum shortname /* * * DON'T EDIT BELOW THIS LINE * * */ (function () { var s = document.createElement('script'); s.async = true; s.type = 'text/javascript'; s.src = '//' + disqus_shortname + ''; (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s); }()); .appendChild(dsq); })();