I know I can create a handler to RequestNavigate event with the following code:
private static readonly ProcessStartInfo s_previewLinkProcessStartInfo = new() { UseShellExecute = true };
private void PreviewLink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
s_previewLinkProcessStartInfo.FileName = e.Uri.AbsoluteUri;
using (Process.Start(s_previewLinkProcessStartInfo))
e.Handled = true;
}
The code above works perfectly. But if I use the same code but with a command, it will throw a System.InvalidOperationException: "Failed to convert resource to object.":
public ICommand PreviewLinkNavigateCommand => new RelayCommand(obj =>
{
s_previewLinkProcessStartInfo.FileName = PreviewLink.NavigateUri.AbsoluteUri;
using (Process.Start(s_previewLinkProcessStartInfo)) { } // throws a System.InvalidOperationException: "Failed to convert resource to object."
});
Xaml:
<TextBlock Padding="10 0 10 0">
<Hyperlink x:Name="PreviewLink" FontSize="14"
NavigateUri="{Binding SelectedMedia.Source.AbsoluteUri}"
Command="{Binding PreviewLinkNavigateCommand}">
Preview link
</Hyperlink>
</TextBlock>
RelayCommand:
internal class RelayCommand : ICommand
{
private readonly Action<object?> _execute;
private readonly Func<object?, bool>? _canExecute;
public event EventHandler? CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public RelayCommand(Action<object?> execute, Func<object?, bool>? canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object? parameter) => _canExecute?.Invoke(parameter) ?? true;
public void Execute(object? parameter) => _execute(parameter);
}
As BionicCode have said I should bind a Command with a CommandParameter as uri.
.xaml.cs:
private static readonly ProcessStartInfo s_previewLinkProcessStartInfo = new() { UseShellExecute = true };
public ICommand PreviewLinkNavigateCommand => new RelayCommand(obj =>
{
s_previewLinkProcessStartInfo.FileName = (string?)obj;
Process.Start(s_previewLinkProcessStartInfo)?.Dispose();
});
.xaml
<TextBlock Padding="10 0 10 0">
<Hyperlink x:Name="PreviewLink" FontSize="14"
Command="{Binding PreviewLinkNavigateCommand}"
CommandParameter="URI">
Preview link
</Hyperlink>
</TextBlock>