[ACCEPTED]-Clicking HyperLinks in a RichTextBox without holding down CTRL - WPF-ctrl

Accepted answer
Score: 29

I found a solution. Set IsDocumentEnabled 8 to "True" and set IsReadOnly to "True".

<RichTextBox IsReadOnly="True" IsDocumentEnabled="True" />

Once 7 I did this, the mouse would turn into a 6 'hand' when I hover over a text displayed 5 within a HyperLink tag. Clicking without 4 holding control will fire the 'Click' event.

I 3 am using WPF from .NET 4. I do not know 2 if earlier versions of .NET do not function 1 as I describe above.

Score: 15

JHubbard80's answer is a possible solution, it's the 6 easiest way if you do not need the content 5 to be selected.

However I need that :P here 4 is my approach: set a style for the Hyperlinks inside 3 the RichTextBox. The essential is to use a EventSetter to make 2 the Hyperlinks handling the MouseLeftButtonDown event.

<RichTextBox>
    <RichTextBox.Resources>
        <Style TargetType="Hyperlink">
            <Setter Property="Cursor" Value="Hand" />
            <EventSetter Event="MouseLeftButtonDown" Handler="Hyperlink_MouseLeftButtonDown" />
        </Style>
    </RichTextBox.Resources>
</RichTextBox>

And in codebehind:

private void Hyperlink_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
    var hyperlink = (Hyperlink)sender;
    Process.Start(hyperlink.NavigateUri.ToString());
}

Thanks 1 to gcores for the inspiaration.

Score: 5

Managed to find a way around this, pretty 13 much by accident.

The content that's loaded 12 into my RichTextBox is just stored (or inputted) as 11 a plain string. I have subclassed the RichTextBox 10 to allow binding against it's Document property.

What's 9 relevant to the question, is that I have 8 an IValueConverter Convert() overload that 7 looks something like this (code non-essential 6 to the solution has been stripped out):

FlowDocument doc = new FlowDocument();
Paragraph graph = new Paragraph();

Hyperlink textLink = new Hyperlink(new Run(textSplit));
textLink.NavigateUri = new Uri(textSplit);
textLink.RequestNavigate += 
  new System.Windows.Navigation.RequestNavigateEventHandler(navHandler);

graph.Inlines.Add(textLink);
graph.Inlines.Add(new Run(nonLinkStrings));

doc.Blocks.Add(graph);

return doc;

This 5 gets me the behavior I want (shoving plain 4 strings into RichTextBox and getting formatting) and 3 it also results in links that behave like 2 a normal link, rather than one that's embedded 1 in a Word document.

Score: 1

Do not handle any mouse events explicitly 10 and do not force the cursor explicitly - like 9 suggested in every answer.

It's also not 8 required to make the complete RichTextBox read-only 7 like (as suggested in another answer).

To 6 make the Hyperlink clickable without pressing the 5 Ctrl key, the Hyperlink must be made read-only e.g., by 4 wrapping it into a TextBlock or by making the complete 3 RichTextBox read-only (by setting RichTextBox.IsReadOnly to false).
Then simply 2 handle the Hyperlink.RequestNavigate event or/and attach an ICommand to the 1 Hyperlink.Command property:

<RichTextBox IsDocumentEnabled="True">
  <FlowDocument>
    <Paragraph>
      <Run Text="Some editable text" />

      <TextBlock>                
        <Hyperlink NavigateUri="https://duckduckgo.com"
                   RequestNavigate="OnHyperlinkRequestNavigate">
          DuckDuckGo
        </Hyperlink>
      </TextBlock>
    </Paragraph>
  </FlowDocument>
</RichTextBox>
Score: 0

Have you tried handling the MouseLeftButtonDown 1 event instead of the Click event?

Score: 0

I changed EventSetter from @hillin's answer. MouseLeftButtonDown didn't 1 work in my code (.Net framework 4.5.2).

<EventSetter Event="RequestNavigate" Handler="Hyperlink_RequestNavigate" />
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
    Process.Start(e.Uri.ToString());
}
Score: 0

My answer is based on @BionicCode's answer, which 14 I wanted to extend with the event handler 13 code, which I had some difficulties to get 12 it working.

<RichTextBox IsDocumentEnabled="True" IsReadOnly="True">
  <FlowDocument>
    <Paragraph>
      <Run Text="Some editable text" />
      <Hyperlink x:Name="DuckduckgoHyperlink" 
        NavigateUri="https://duckduckgo.com">
        DuckDuckGo
      </Hyperlink>
    </Paragraph>
  </FlowDocument>
</RichTextBox>

I changed his code slightly:

  1. I wanted the RichTextBox to be readonly. When the RichTextBox is readonly, it is not necessary to put the HyperLink into a TextBlock. However, using TextBlock in a RichTextBlock where the user can make changes is a great suggestion.
  2. In my programming style, code related stuff belongs in the code behind file. Event handlers are code and I prefer to even add the event handler to its control from code behind. To do that, it is enough to give the Hyperlink a name.

Code behind

I 11 needed to display some rich text with links 10 in a HelpWindow:

public HelpWindow() {
  InitializeComponent();

  DuckduckgoHyperlink.RequestNavigate += Hyperlink_RequestNavigate;
}


private void Hyperlink_RequestNavigate(object sender, 
  RequestNavigateEventArgs e) 
{
  Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) {
    UseShellExecute = true,
  });
  e.Handled = true;
}

Note that the same event handler can 9 be used by any HyperLink. Another solution would 8 be not to define the URL in XAML but hard 7 code it in the event handler, in which case 6 each HyperLink needs its own event handler.

In various 5 Stackoverflow answers I have seen the code:

Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));

Which 4 resulted in the error message:

System.ComponentModel.Win32Exception: 'An error 3 occurred trying to start process 'https://duckduckgo.com/' with 2 working directory '...\bin\Debug\net6.0-windows'. The 1 system cannot find the file specified.'

More Related questions