Nested TextBlocks and Hyperlinks, How do you replicate this XAML in C#?
I have this XAML:
<TextBlock TextWrapping="Wrap" Foreground="Green"
Text="This is some Green text up front. ">
<TextBlock Foreground="Blue">
This is some Blue text.
</TextBlock>
This is some Green text following the Blue text.
<Hyperlink>
<TextBlock Text="And finally, this is a Hyperlink." TextWrapping="Wrap"/>
</Hyperlink>
</TextBlock>
And I'd like to know how to replicate it procedurally in C#.
I know how to create TextBlock
s in C# with something like:
TextB开发者_开发问答lock tb = new TextBlock();
tb.Text="Some text"
And I can put multiple TextBlock
s together in a panel within C#. But I don't see how you go about putting TextBlock
s into other TextBlock
s, and TextBlock
s into Hyperlink
s into TextBlock
s.
Are some container objects and extra TextBlock
objects being created automatically, somehow? Or does the TextBlock
have some methods/properties that allow it to contain the other items?
Other related questions:
1. What's the best way to add something like a Click() event to theHyperlink
?
2. Is there a way to get the blue text to wrap more cleanly? In the above XAML, as soon as the rightmost word would need to wrap, the entire block of blue text is wrapped instead.
Thanks for any illumination you can provide.
You can modify the collection of Inlines exposed via the TextBlock's Inlines property. The above XAML sample would look a little something like this:
TextBlock tb = new TextBlock
{
Text = "This is some Green text up front.",
Foreground = Brushes.Green
};
InlineCollection tbInlines = tb.Inlines;
tbInlines.Add(new Run
{
Text = "This is some Blue text.",
TextWrapping = TextWrapping.Wrap,
Foreground = Brushes.Blue
});
tbInlines.Add(new Run
{
Text = "This is some Green text following the Blue text."
});
Run hyperlinkRun = new Run("And finally, this is a Hyperlink.");
tbInlines.Add(new Hyperlink(hyperlinkRun));
As for your related questions:
1A) While it's possible to hook an event handler to every single Hyperlink instance using the RequestNavigate event on the class, that can be costly to setup and use more memory than is necessary. Instead I recommend leveraging routed events and simply hooking the RequestNavigate event at the container where all of your hyperlinks will be. You can do this like so:
myContainer.AddHandler(
Hyperlink.RequestNavigateEvent,
new RequestNavigateEventHandler(
(sender, args) =>
{
/* sender is the instance of the Hyperlink that was clicked here */
}));
2A) In your XAML example it's treating the inner TextBlock as an element that needs to be wrapped all together. If you're using my Run based approach the wrapping should be inherited from the containing text block.
I don't know about TextBlocks, but here is how you would do it in a RichTextBox. You could use a RichTextBox instead of a TextBlock.
RichTextBox rtbTest = new RichTextBox();
rtbTest.IsDocumentEnabled = true;
FlowDocument fd = new FlowDocument();
Paragraph para = new Paragraph();
Run r4 = new Run("Some Text To Show As Hyperlink");
Hyperlink h4 = new Hyperlink(r4);
h4.Foreground = Brushes.Red; //whatever color you want the HyperLink to be
// If you want the Hyperlink clickable
h4.NavigateUri = new Uri("Some URL");
h4.RequestNavigate += new RequestNavigateEventHandler(h_RequestNavigate);
// Leaving the two previous lines out will still make the Hyperlink, but it won't be clickable
// use this if you don't want an underline under the HyperLink
h4.TextDecorations = null;
para.Inlines.Add(h4);
fd.Blocks.Add(para);
rtbTest.Document = fd;
For normal text, I just used the HyperLink, but removed the two lines that made it clickable. This would give the text the color, but it wouldn't be clickable. Though it still makes the cursor change still. Though I am sure there is a property to change that also.
精彩评论