Provide source span in LinkClicked handler of RichTextBox
See original GitHub issueThis supersedes #4419 and #4418
Is your feature request related to a problem? Please describe.
(1) When using RichTextBox
with hyperlinks and handling LinkClicked
you get either passed the source text of the link or (in case of the official hyperlink markup) the hidden text containing the hyperlink. The documentation contains instructions of how to obtain the display text if you need it, but currently it is not possible to follow these instructions in WinForms because the span clicked is not known. You could search for the hyperlink text in the source text but if you have the same link multiple times with different display texts its not possible to know which you clicked.
(2) In older versions of the RichTextBox
control (before the .NET 4.7 series switched to a newer native control) it was possible to make hidden text part of the link, which would be included when invoking the LinkClicked
event. This is no longer possible because the current version of the native control does not allow hidden text to be part of a link (it will remove the link attribute from hidden text and split the link into multiple parts, see #4418)
(3) Besides these two scenarios there’s also the general use-case of wanting to click a hyperlink and then modify the document around that link (e.g. by erasing a section or adding additional details to a section). For this it would be useful to know the source span as well.
Describe the solution you’d like and alternatives you’ve considered
All three scenarios are possible to work around so this is not a blocking problem, but having the source span available would be more convenient since you don’t have to maintain a collection of unique identifiers.
- workaround for (1) is to give hyperlinks unique identifiers and map those to the actual URLs in a dictionary. To access the display text (if you don’t want to just put it in the dictionary as well) you can then search for the unique identifier in the source text and find the span clicked. From there you can get the display text according to the official documentation.
- workaround for (2) is to not use hidden text to pass information to the
LinkClicked
handler (this simply doesn’t work anymore). Instead use the official hyperlink markup and either pass the hidden information as hyperlink, or generate a unique identifier and lookup your information from that. - workaround for (3) is to generate unique identifiers and use hyperlink markup, then find them in the source text and perform your edits around them
However, given that WinForms already has obtained the information about the source span from the native control it would be nice to just pass it on to managed code.
Suggested API:
public class LinkClickedEventArgs : EventArgs
{
public LinkClickedEventArgs(string linkText); // existing (keep for compatibility, perhaps mark obsolete)
+ public LinkClickedEventArgs(string linkText, int linkStart, int linkLength); // new
public string LinkText { get; } // existing
+ public string LinkStart { get; } // new, default to zero if not specified
+ public string LinkLength { get; } // new, default to zero if not specified
}
The naming of the new properties is chosen to match the existing SelectionStart
and SelectionLength
properties.
I’d keep the existing constructor since it was publicly accessible previously and people may have created instances of this event (unlikely but not unreasonable, e.g. if you want to reuse event handler code and call it outside of the event).
The existing constructor would use LinkStart=0
and LinkLength=0
to indicate that no link span is available, yet the span is always valid to index into RichTextBox.Text
so callers don’t need to explicitly check (they’d get back an empty string if they index the source text unconditionally).
The new constructor should verify linkStart
and linkLength
to not be negative, as well as not overflowing when added (its unreasonable to have every user of the event safeguard its logic against overlow, much better to do it just once in the constructor). It would not verify that the span lies within the RichTextBox.Text
because it has no reference to it and can be constructed independently.
(I’ll add some examples later how to make use of the source span, but it is nothing surprising, just indexing into RichTextBox.Text
or using interop to access the ITextRange
if you need richer API. While it would be nice to have a managed API over the ITextDocument
interop, having the source span in the event is really the most important missing information as you cannot easily obtain it via custom interop, unless you subclass the control and catch the native LinkClicked notification before WinForms does.)
Will this feature affect UI controls?
This affects the coding against UI controls, but not their appearance or design time.
Issue Analytics
- State:
- Created 3 years ago
- Comments:8 (8 by maintainers)
@weltkante would you like to have a go at implementing it?
Verified in the latest .Net 6.0 P4 build: 6.0.100-preview.4.21224.2, it provided link span: LinkStart and LinkLength for LinkClickedEventArgs