I need to create an WPF app in which I'm showing text that is scraped from a site. In every new day, the text is changed. Nevertheless, the problem is that this text contains hyperlinks, and I need to scrape them also. In this sense, I am scraping the innerHtml and modifying to be readable to XAML.
Suppose I am scraping this HTML:
<p>Click <a href="google.com"> here </a> !!</p>
I modify this to be readable to XAML like this:
<TextBlock> Click <Hyperlink RequestNavigate=\"Hyperlink_RequestNavigate\" NavigateUri='https://www.google.com/'> here </Hyperlink> !!! </TextBlock>
How am I doing this?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var str = " Click <Hyperlink RequestNavigate=\"Hyperlink_RequestNavigate\" NavigateUri='https://www.google.com/'> here </Hyperlink> !!! ";
grid.Children.Add(CreateTextBlock(str));
}
public TextBlock CreateTextBlock(string inlines)
{
var xaml = "<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">"
inlines "</TextBlock>";
return XamlReader.Parse(xaml) as TextBlock;
}
public void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
e.Handled = true;
}
}
All good until now, but the error above comes in:
System.Windows.Markup.XamlParseException: ''Failed to create a 'RequestNavigate' from the text 'Hyperlink_RequestNavigate'.' ArgumentException: Cannot bind to the target method because its signature is not compatible with that of the delegate type.
Thank you for the help.
CodePudding user response:
The XamlReader.Parse()
will not allow dynamically attach the RequestNavigate
event handler this way. But you can do the following:
- Add a name to the
Hyperlink
. - Load/Parse the XAML without
RequestNavigate
. - Add the
RequestNavigate
event handler programmatically.
public MainWindow()
{
InitializeComponent();
var str = " Click <Hyperlink Name=\"hyperName\" NavigateUri=\"https://www.google.com/\"> here </Hyperlink> !!! ";
grid.Children.Add(CreateTextBlock(str));
}
public TextBlock CreateTextBlock(string inlines)
{
var xaml = "<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" inlines "</TextBlock>";
var tb = XamlReader.Parse(xaml) as TextBlock;
if (tb != null && tb.FindName("hyperName") is Hyperlink hyperln)
{
hyperln.RequestNavigate = Hyperlink_RequestNavigate;
}
return tb;
}
public void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
...
}
CodePudding user response:
The XamlReader.Parse
method doesn't support event handlers but you could simply remove RequestNavigate="Hyperlink_RequestNavigate"
from the XAML being parsed and handle the RequestNavigate
event for all hyperlinks by attaching an event handler for the routed event to the Grid
:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var str = " Click <Hyperlink NavigateUri='https://www.google.com/'> here </Hyperlink> !!! ";
grid.Children.Add(CreateTextBlock(str));
grid.AddHandler(Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler(Hyperlink_RequestNavigate));
}
public TextBlock CreateTextBlock(string inlines)
{
var xaml = "<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">"
inlines "</TextBlock>";
return XamlReader.Parse(xaml) as TextBlock;
}
public void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
e.Handled = true;
}
}