Why TextElemt class is not derived from Control class? - c#

Consider this Xaml:
<RichTextBox>
<Document>
<Paragraph>
<Run Text="FirstWord " />
<Run Text="SecondWord"/>
</Paragraph >
<Paragraph>
<Run Text="FirstWord " />
<Run Text="SecondWord"/>
</Paragraph >
</Document>
</RichTextBox >
Now, assume that for some reasons I use something like this:
<StackPanel Orientation = "Vertical">
<StackPanel Orientation = "Horizontal"> // as a Paragraph
<TextBlock Text="FirstWord " />
<TextBlock Text="SecondWord"/>
</StackPanel>
<StackPanel Orientation = "Horizontal"> // another Paragraph
<TextBlock Text="FirstWord " />
<TextBlock Text="SecondWord"/>
</StackPanel>
</StackPanel>
A Run or a Paragraph or other TextElements are not Controls and therefore there is no ArrangeOverride or MesureOverride methods for them. My question is why they are not controls? is it because of performance issues or there is not much difference between measuring size, arranging and rendering of a TextElement and a Control? In other words, what is the benefits of the first Xaml over the second one (apart from its appearance)?
Thanks.

They are not controls because they are not separate from the rest of the document. What you are setting inside the document are not child controls, but the content of the document. The rendering is done completely inside the RichTextBox.
The main difference between first and second example is that RichTextBox allows you to create flowing text with parts of text having different formatting. While it is possible to do it by using normal TextBlocks, it would be hard to fine-tune for things like line-breaks and dynamic resizing.

Related

NavigationView Item with extra content on right side

I have a NavigationView in my app. I want to add counters/badges to some of the items. But whatever I do, the badge always stays right next to the label. See the image below (on the top is what I have, on the bottom what I want to achieve)
The code I'm currently using is the following:
<NavigationViewItem Icon="Mail">
<NavigationViewItem.Content>
<RelativePanel HorizontalAlignment="Stretch">
<TextBlock RelativePanel.AlignLeftWithPanel="True">Inbox</TextBlock>
<local:Badge RelativePanel.AlignRightWithPanel="True" BadgeText="30"/> <!-- can be replaced with a simple "TextBlock" -->
</RelativePanel>
</NavigationViewItem.Content>
</NavigationViewItem>
(You can subsitute the Badge control with a simple TextBlock)
The problem is that RelativePanel can't get SplitViewOpenPaneThemeLength automatically. so we need specific the width for RelativePanel. As we known SplitViewOpenPaneThemeLength is 320, and SplitViewCompactPaneThemeLength is 48. so the
width of NavigationViewItem.Content is 320-48 = 272. Please refer the following xaml code.
<RelativePanel HorizontalAlignment="Stretch" Width="{ThemeResource SplitViewOpenPaneThemeLength}">
<TextBlock RelativePanel.AlignLeftWithPanel="True">Inbox</TextBlock>
<TextBlock RelativePanel.AlignRightWithPanel="True" Text="30" Margin="0,0,48,0"/>
<!-- can be replaced with a simple "TextBlock" -->
</RelativePanel>

How to add TextBlock inside MahApps Tile?

I want to add a TextBlock inside a MahApps Tile's title (having in mind binding portions of the text with some properties). I've tried this, but it says "Property does not support values of type TextBlock".
<mah:Tile>
<mah:Tile.Title>
<TextBlock>
</TextBlock>
</mah:Tile.Title>
How can it be done?
The Title property of the Tile explicitly wants a String to be passed, so you can't link a TextBlock here.
You can now do the following:
Overwrite the Template of the Tile: This gives you complete freedom of how to structure the appearance, but you may easily lose some of the behaviors of the Tile
My recommendation: Leave the Title of the Tile blank and overwrite the ContentTemplate of the Tile to simply show your own Title TextBlock besides the main content of the Tile. In this case the viewmodel that you are binding to the tile could have a Body and a Title property and your xaml including datatemplate could look like:
With this you can also move the Title to any position you like
<mah:Tile DataContext="yourViewModel">
<mah:Tile.ContentTemplate>
<DataTemplate>
<DockPanel LastChildFill="True">
<TextBlock Text="{Binding Title}" DockPanel.Dock="Bottom" />
<ContentControl Content="{Binding Body}" />
</DockPanel>
</DataTemplate>
</mah:Tile.ContentTemplate>
</mah:Tile>

Having links in a binding

I'm binding text in LocalizedResources (for various languages) and I need to have links inside that text. Unfortunately when I bind it like this I can't have links in it:
<TextBlock TextWrapping="Wrap" Text="{Binding Path=LocalizedResources.AboutText, Source={StaticResource LocalizedStrings}}"/>
So I basically want to make some of the words in that block of text links. Is that possible?
EDIT: I need something like this
Except I'm binding this text from LocalizedResources as I said
As Romasz suggested, you should use RichTextBox instead of a TextBlock. You can solve the binding there with the following code:
<RichTextBox>
<Paragraph>
<Run Text="{Binding Path=LineFormatted}" />
</Paragraph>
</RichTextBox>
For the hyperlinks, you can go through the whole text using C# and than separate the link from the text (you can use something like --- and than you know that whenever a --- appears in the text, you have a hyperlink).
Once you have a text and a hyperlink, you can add them to the RichTextBox using the following code:
Run myRun = new Run();
myRun.Text = "Displaying text with ";
Hyperlink link = new Hyperlink();
link.Inlines.Add("hyperlink");
link.NavigateUri = new Uri("https://stackoverflow.com/");
link.TargetName = "_blank";
link.Foreground = new SolidColorBrush(Colors.Blue);
Paragraph myParagraph = new Paragraph();
myParagraph.Inlines.Add(myRun);
myParagraph.Inlines.Add(link);
myRun = new Run();
myRun.Text = " and with some text after the link.";
myParagraph.Inlines.Add(myRun);
rtb.Blocks.Add(myParagraph);
Where rtb is the name of my RichTextBox.
Straightforward solution would be as follows:
Split your text into few chunks, for example
. before link 1
. link 1
. before link 2
. link 2
. after link 2
create textblock for every before/after link section and add hyperlink button for links.
You should be able to blend thgether these parts, so that user won't distinguish text and links
Hope this helps
That is the code:
<TextBlock FontSize="20">
<Run x:Uid="one" />
<Run x:Uid="link_description" Foreground="BlueViolet">
<iact:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:OpenHyperlinkAction x:Uid="link" />
</core:EventTriggerBehavior>
</iact:Interaction.Behaviors>
</Run>
<Run x:Uid="two" />
</TextBlock>
Or:
<TextBlock FontSize="20">
<Run x:Uid="one" />
<Hyperlink x:Uid="link" Foreground="BlueViolet" >
<Run x:Uid="link_description" />
</Hyperlink>
<Run x:Uid="two" />
</TextBlock>

WPF- Cut-off issue in WrapPanel

when i use more than one controls inside the wrap Panel if any control contains lengthy text (more than the window size) cut-off is happening. (See the image)
I have two textblocks and one button control.
<Grid>
<WrapPanel>
<TextBlock Text="Very long Text Message contains long text for testing " FontWeight="Bold"></TextBlock>
<Button Content="sample Text"></Button>
<TextBlock Text="sample Text textblock"></TextBlock>
</WrapPanel>
</Grid>
the cut-off happens for first text block. i want wrap to next line if the text contains more characters.
help me to solve the issue. thanks in advance.
You need the attribute TextWrapping="Wrap" in your textbox
<TextBlock
Text="Very long Text Message contains long text for testing "
FontWeight="Bold"
TextWrapping="Wrap">
</TextBlock>
Are you trying to make a single paragraph that wraps? If so, then WrapPanel isn't actually what you want.
WrapPanel takes UI elements (rectangular chunks of real estate) and lays them out left-to-right, top-to-bottom. You could enable wrapping in your first TextBlock, but then it'll take up a rectangle of screen space that's two lines high. Because the TextBlock fills that entire rectangle, the button will actually appear under it, rather than to the right of the bold words "for testing ".
If you want to make the whole thing flow like a paragraph, you don't want to use UI elements (which are always rectangular chunks); you want to use text elements (which flow in paragraphs).
The way to get text elements into your XAML is to wrap them in a TextBlock. Try this:
<Grid>
<TextBlock TextWrapping="Wrap">
<Bold>
<Run Text="Very long Text Message contains long text for testing " />
</Bold>
<Button Content="sample Text"></Button>
sample Text textblock
</TextBlock>
</Grid>
Note that I wrapped the first chunk of text in a <Run> element -- otherwise the trailing space would be ignored (assumed to be whitespace in your XAML document). The second chunk of text didn't have leading or trailing spaces, so I just put it directly inline.
This answer has a bit more about the difference between the "controls" and "text" sides of XAML.

Building comment tree efficiently in Metro XAML

I am trying to build a 'comments control' (In a win8 XAML app, which is similar to Silverlight) which will load and render a comment tree for the user.
Each comment can have 0 or 1+ children comments (which recurses through each comment).
Each comment displays a set of info, including author, time, the comment itself, etc.
The approach I initially took to build this is to use a ListView which has a 'CommentItem' control binding.
<TextBlock Grid.Row="1" TextWrapping="Wrap" Text="{Binding commentText}" FontSize="11" FontFamily="Global User Interface" />
<ListView Grid.Row="2" x:Name="CommentRepliesList" ItemsSource="{Binding}" >
<ListView.ItemTemplate>
<DataTemplate>
<local:CommentItem Tag="{Binding}"></local:CommentItem>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The above will just recurse through each comment, apply the comment text, and then create a new commentitem for each comment child, recurse through again, etc.
The issue, however, is this is extremely slow and non-performant.
Does anyone know a more efficient way to do this? Is ListView the appropriate control to use for this?

Categories

Resources