Unfortunately there's no easy way to do that... As far as I know, the best you can do is return a XAML string and use a converter to parse it.
Warning: ugly code ahead...
XAML
<Window.Resources>
<local:XamlToTextBlockConverter x:Key="xamlConverter" />
</Window.Resources>
<Grid>
<ContentControl Content="{Binding MyTextWithHyperlink, Converter={StaticResource xamlConverter}}" />
</Grid>
Converter
public class XamlToTextBlockConverter : IValueConverter
{
#region Implementation of IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string xaml = value as string;
if (xaml == null)
return Binding.DoNothing;
const string textBlockFormat =
@"<TextBlock xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</TextBlock>";
string fullXaml = string.Format(textBlockFormat, xaml);
return (TextBlock)XamlReader.Parse(fullXaml);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
ViewModel
public string MyTextWithHyperlink
{
get { return "Click <Hyperlink Command=\"{Binding MyCommand}\">here</Hyperlink> to continue"; }
}
Note the use of a ContentControl
rather than a TextBlock
: that's because the TextBlock.Text
property can only contain plain text, not a formatted document, and the Inlines
property cannot be bound because it's not a dependency property (and anyway it's readonly). Instead we manually create a TextBlock
in the converter and assign it to the content of the ContentControl
.
It's definitely not a very elegant solution, but it works...