Clickable link inside a text control like RichTextControl in WPF? - c#

I want to be able to have some text clickable like in webpages in WPF. The control should have both non-functional text (for display) both also some of its parts as completely clickable.
Say like Wikipedia.
But this is an independent standalone offline app.
I tried various things but I couldn't do it, especially the clicking doesn't function like web pages, i.e. 1 click to open the url contained within the tools.

If you don't have a requirement that it be a full-blown FlowDocument, then you can just use a plain old WPF TextBlock, and put Hyperlinks in it.
<TextBlock>
Here's some text with a
<Hyperlink NavigateUri="Page2.xaml">link to another XAML page</Hyperlink>
and a
<Hyperlink NavigateUri="http://msdn.microsoft.com/">link to the
Web</Hyperlink>.
</TextBlock>
If you need scrolling, just put a ScrollViewer around it.
If you need the paginated, multi-column viewer, then you'll need to go with an all-out FlowDocument, but if all you want is text with hyperlinks, TextBlock + Hyperlink should be all you need.

you should try setting the flow document manually and creating hyperlinks within the flow document...
Here is some text taken from the following link:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/99ae9d9c-1dd4-4acd-8d5d-6eb739adeb98
"
Hi,
It is possible.
Here is a small example of creating hyperlink to paragraph/section/table.
In order to navigate to website, we can create a Frame Control for navigation. The hierarchical relationship of elements in this example is like this :
Frame-->FlowDocument-->Table-->Section-->Paragraph-->Hyperlink
In the code behind:
public Window1()
{
InitializeComponent();
// add a Frame for navigation
Frame frame = new Frame();
this.Content = frame;
//add FlowDocument
FlowDocument doc = new FlowDocument();
frame.Navigate(doc);
//add Table
Table table = new Table();
doc.Blocks.Add(table );
TableRowGroup group = new TableRowGroup();
table.RowGroups.Add(group );
TableColumn col1 = new TableColumn();
TableColumn col2 = new TableColumn();
table.Columns.Add(col1 );
table.Columns.Add(col2);
TableRow row1 = new TableRow();
TableCell cel1 = new TableCell();
row1.Cells.Add(cel1);
group.Rows.Add(row1);
//add Section
Section mySection = new Section();
//add section to the Table cell.
cel1.Blocks.Add(mySection);
Paragraph paraValue = new Paragraph();
Hyperlink hl = new Hyperlink(new Run("Click Here to Google"));
hl.Foreground = Brushes.Red;
paraValue.Inlines.Add(hl);
hl.FontSize = 11;
hl .NavigateUri =new Uri ("Http://www.google.cn");
mySection.Blocks.Add(paraValue);
}
If you have any additional question about this,please feel free to ask.
Thanks. "

Related

How to query the Base Paragraph element position? in order to add Link Annotation without saving the file

I'm creating a simple PDF file with some text and an hyperlink attached to the that text:
Document pdfDocument = new Document();
Page pdfPage = pdfDocument.Pages.Add();
TextFragment textFragment = new TextFragment("My Text");
Table table = new Table();
Row row = table.Rows.Add();
Cell cell = row.Cells.Add();
cell.Paragraphs.Add(textFragment);
pdfPage.Paragraphs.Add(table);
LinkAnnotation link = new LinkAnnotation(pdfPage, textFragment.Rectangle); //[Before Save]textFragment.Rectangle: 0,0,35.56,10
link.Action = new GoToURIAction("Link1 before save");
pdfPage.Annotations.Add(link);
pdfDocument.Save(dataDir + "SimplePDFWithLink.pdf");
The problem is that the link annotation is being assign to the before save rectangle [0,0,33.56,10] at the bottom of the screen where's the textFragment is being added to a different rectangle (I can't set here the Position property because I don't know it, it is relative to the cell's table).
In order to solve this I've tried saving the page and only then searching the textFragment using TextFragmentAbsorber
pdfDocument.Save(dataDir + "SimplePDFWithLink.pdf");
//[After Save]textFragment.Rectangle: 0,0,90,770
TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber();
pdfPage.Accept(textFragmentAbsorber);
foreach (TextFragment absorbedTextFragment in textFragmentAbsorber.TextFragments)
{
link = new LinkAnnotation(pdfPage, absorbedTextFragment.Rectangle);
link.Action = new GoToURIAction("Link 2 after save");
pdfPage.Annotations.Add(link);
}
pdfDocument.Save(dataDir + "SimplePDFWithLink.pdf");
My Question:
Is is possible to add a simple link to a TextFragment (which is BaseParagraph not StructureElement) without saving the document first?
Here is a simple demo of the outcome, you can see that before saving the document the link is added to the left bottom of the document instead of the text rectangle:
Update:
If I specify the TextFragment's Position value with some arbitrary values, the link is then added exactly to the text, but I don't know what will be the Position value of the element because it being built dynamically using a Table.
Working with TextFragment and TextSegment does work and adds the link without pre-saving the file:
TextFragment textFragment = new TextFragment("My Text");
TextSegment textSegment = new TextSegment("Link to File");
textSegment.Hyperlink = new Aspose.Pdf.WebHyperlink("www.google.com");
textFragment.Segments.Add(textSegment);
It is worth to mention it is works well when linking to a file on the user's file-system like:
textSegment.Hyperlink = new Aspose.Pdf.WebHyperlink("Files\foo.png");

How to remove hyperlink underline from code behind?

I am parsing HTML, generating a various blocks and adding them to RichTextBlock control. However, when I generate a Hyperlink from code behind I don't know how to remove underline property. I've seen posts about creating a HyperlinkButton and setting its Content property but it is definitely not something that I want because I can't make it to be in line with the rest of the text and it looks awful.
Below is the relevant code for generating a hyperlink:
private static Inline GenerateHyperLink(HtmlNode node)
{
Span s = new Span();
InlineUIContainer iui = new InlineUIContainer();
Hyperlink link = new Hyperlink();
link.Inlines.Add(new Run() { Text = node.InnerText });
link.NavigateUri = new Uri(node.Attributes["href"].Value, UriKind.Absolute);
s.Inlines.Add(link);
s.Inlines.Add(new Run() { Text = " " });
return s;
}
From MSDN:
A Hyperlink has a class inheritance that doesn't include
FrameworkElement, so it doesn't have a Style property. Nor does a
Hyperlink have a Template (it's not a true control).
Does it mean that there is no way to achieve that using Hyperlink element?

How to create a pop up window when a button is clicked

This is the code I have for the button. I want the configbutton to display a pop up window when clicked on. I have looked up and tried a lot of different codes but none of them work. I feel like I am missing a key component but I am not sure what that is. Appreciate the help!
tr = new TableRow();
// Create the cell
tc = new TableCell();
tc.Width = Unit.Point(300);
tc.BorderWidth = 0;
tc.BorderStyle = BorderStyle.None;
Button ConfigButton = new Button();
ConfigButton.Text = "Configuration";
ConfigButton.Visible = true;
tc.Controls.Add(ConfigButton);
tr.Cells.Add(tc);
tbl.Controls.Add(tr);
Using JavaScript Along with ASP.NET you will do the following:
// when you create the button, you can add attributes
Button ConfigButton = new Button();
// this example will display alert dialog box
ConfigButton.Attributes.Add("onclick", "javascript:alert('ALERT ALERT!!!')");
// to get you popup windows
// you would use window.open with the BLANK target
ConfigButton.Text = "Configuration";
ConfigButton.Visible = true;
I recommend looking into using the AJAX Control Toolkit ModalPopupExtender. This is what I use for my pop ups in ASP.NET.
Here is a link to he AJAX Control Toolkit samples website showing how this control works:
http://www.ajaxcontroltoolkit.com/ModalPopup/ModalPopup.aspx

Bind RichTextBox without typing a lot of useless code or add HyperLinks to strings?

I had a class with <toolkit:ExpanderView>-elements. Those are bound to a ViewModel and need to stay bound, because I'm already using a lot of checks like "Which VM-element is expanded and which not", etc.
The text inside of that expanded part was read from localized Strings (AppResources.resx) and added inside of the VM. But now I have to add hyperlinks to that text.
My idea was to throw away the localized strings for a while and create RichTextBoxes inside of the ViewModel. Instead of binding strings to the expanded part I would bind the RichTextBoxes.
But all methods I find suck. e.g.:
StackPanel tempGrid = new StackPanel();
StackPanel tempGrid = new StackPanel();
RichTextBox tempRtb = new RichTextBox();
Paragraph tempPara = new Paragraph();
Run tempRun = new Run();
Hyperlink tempHLink = new Hyperlink();
tempHLink.Click += Hyperlink_Click;
tempRun.Text = "line 1\nline 2\nline 3";
tempPara.Inlines.Add(tempRun);
tempRun.Text = "\nTel.: ";
tempPara.Inlines.Add(tempRun);
tempHLink.Inlines.Add("+01800 000 000 000");
tempPara.Inlines.Add(tempHLink);
tempRun.Text = "\nE-Mail: ";
tempPara.Inlines.Add(tempRun);
tempHLink.Inlines.Add("e-mail#email.com");
tempPara.Inlines.Add(tempHLink);
But it fails already when I reuse tempRun. Should I add thousands of new variables? ôo
Also the in the spec ( http://msdn.microsoft.com/en-us/library/system.windows.documents.run.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1 ) it says that something like
Run run = new Run("string");
should work. But it doesn't with WP8 and turns to
Run run = new Run();
run.text = "string";
So everything becomes WAY longer... :(
Edit:
Yes, forgot to ask the actual question: Is there a faster way to fill a richtextbox or paragraph with lots of Run or Hyperlink-elements?
And how do I bind it in my xaml?
I need something like:
<DataTemplate>
<RichTextBox Content="{Binding MyModelViewParagraph}"/>
</DataTemplate>
to bind my paragraph from the ViewModel to the xaml.
Okay, googling further lead me to this:
ViewModel:
StackPanel tempStack = new StackPanel();
RichTextBox tempRtb = new RichTextBox();
Paragraph tempPara = new Paragraph();
//tempHLink.Click += Hyperlink_Click;
tempPara.Inlines.Add(new Run { Text = "text 1\ntext 2\n text 3" });
tempPara.Inlines.Add(new Run { Text = "\nTel.: " });
//tempInline.Add(new Hyperlink { new InlineCollection { = } }) // "+000 (0) 00 00 00-0"
tempPara.Inlines.Add(new Run { Text = "\nE-Mail: " });
//tempInline.Add(new Hyperlink { new InlineCollection { = } }) // e-mail#email.com
tempRtb.Blocks.Add(tempPara);
tempStack.Children.Add(tempRtb);
Still need to find out how exactly I give Text and Click-Event to every HyperLink but that'll be managable I guess..
xaml:
<DataTemplate>
<Grid>
<ContentPresenter Content="{Binding Content}"/>
</Grid>
</DataTemplate>
That binds my Stackpanel so I can add as many elements as I need.
Sorry for answering it by myself. Sometimes you seem to be stuck and it's better to ask then lose 2-3 more days on something that might be simple.. And sometimes asking the question leads you to a solution. In my case it was just mroe stupid googling and reading the MS-specification xD
Edit:
If someone ants to know the whole solutionf ro the Hyperlinks as well - I found out :)
tempPara.Inlines.Add(CreateHyperlinkWithContent("+00 (00) 00 00 00-0"));
With the method:
private Hyperlink CreateHyperlinkWithContent(string content)
{
Hyperlink tempHyperLink = new Hyperlink();
tempHyperLink.Inlines.Add(content);
tempHyperLink.Click += Hyperlink_Click;
tempHyperLink.Foreground = new SolidColorBrush(Color.FromArgb(0xff, 0x33, 0x66, 0x99));
tempHyperLink.MouseOverForeground = new SolidColorBrush(Color.FromArgb(0xff, 0x33, 0x66, 0x99));
return tempHyperLink;
}
This is the shortest way I could find to add Text and Links in a single Line everytime ;)

HyperLink text not rendered after controls are added

I have a HyperLink control with text in its Text property.
With the following code:
var link = new HyperLink();
var img = new HtmlGenericControl("img");
img.Attributes.Add("src", "text.png");
link.Text = "Test";
link.Controls.Add(img);
When I do this, the image is rendered inside a a tag, but the text is not rendred.
Is there a way to render both the image and the text inside the Text property without throwing a third control in to the mix?
When you put any controls into the WebControl.Controls collection, it will ignore what you have inside Text. So if you want to render both text and other child controls, you should add the text into Controls:
var link = new HyperLink();
var img = new HtmlGenericControl("img");
img.Attributes.Add("src", "text.png");
link.Controls.Add(new Literal{ Text = "Test"}); // this line will add the text
link.Controls.Add(img);
I feel this should work out for you.
var link = new HyperLink();
var img = new HtmlGenericControl("img");
var lbl = new Label();
img.Attributes.Add("src", "text.png");
lbl.Text = "Test";
link.Controls.Add(img);
link.Controls.Add(lbl);
this.Controls.Add(link);
According to the MSDN article "The HyperLink control can be displayed as text or an image." So the answer is no, I'm afraid.

Categories