Binding list of paragraphs to RichTextBlock - c#

Right now, I have the data I need binding to a RichTextBlock, but I'm unable to format it, since I'm just using one long string bound to the run on a paragraph setup in my RichTextBlock. Obviously, this isn't ideal. I would like to be able to change font sizes or font weights for some words, but can't see of a way to do that with my current method.
<RichTextBlock TextAlignment="Justify" TextWrapping="WrapWholeWords" Name="richTB">
<Paragraph>
<Run Text="{Binding}" />
</Paragraph>
</RichTextBlock>
I know I can create a RichTextBlock in my code behind, and add paragraphs manually to that, but how would I bind it? Since it's in my page.resources?

Unfortunately you can't really bind it if you want to do custom formatting on the string. XAML builds those controls, and you can't really generate those controls through a binding the way you want.
What you could do is hook up an OnLoad event handler for your control, and inject whatever paragraph/run controls via C#.

I believe you are {binding} the source and hence inside the Code, you can take help from this code:
Paragraph para = new Paragraph();
para.Inlines.Add(new Run { Text = sample, FontSize = 15 });
rtb.Blocks.Add(para);
where rtb is a richtextblock.

Related

Set TextBlock Content by bound C# property (WPF and Caliburn.Micro)

If it helps to know, I'm using Caliburn.Micro, and have laid out everything based on the MVVM framework requirements as I understand them.
Here is the relevant XAML ...
<ListView ItemsSource="{Binding ProductListBox}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding ProductID}"/>
<TextBlock Text="{Binding ProductDescription}"/>
<TextBlock Text="{Binding ProductDescriptionExtended}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The above content of the ListView is created dynamically based on the content of ProductListBox, which sits inside this class...
public class MainViewModel : Screen
{
public List<ProductModel> ProductListBox { get; private set; }
public void GetProductsButton()
{
DBAccess db = new DBAccess();
ProductListBox = db.GetProducts(SearchTextBox);
NotifyOfPropertyChange(() => ProductListBox);
}
}
That List is populated when a Button is clicked, it causes the above GetProductsButton() method to start.
Over in the DBAccess class, in the GetProducts method I would like to change the format of the text in the ProductListBox<>.ProductDescription. Its a string, but I'm happy to change it to any type should it help the cause!
The kind of change I would like to achieve is simply (highlighting) changing the background color of selected text based on found search terms the user had typed in, that the bound XAML TextBlock will then display.
What I cant work out is how to highlight any text at this time via C#, that will then be displayed purely by the bound XAML control... I've only been able to do it by hardcoding XAML which is not going to help for what I'm trying to achieve.
In the DBAccess class and inside the GetPeoducts method, this is the kind of thing I have tried in order to make this happen...
I've pasted in this code...
TextBlock textBlock1 = new TextBlock();
textBlock1.Inlines.Add(new Bold(new Run("TextBlock")));
textBlock1.Inlines.Add(new Run(" is designed to be "));
textBlock1.Inlines.Add(new Italic(new Run("lightweight")));
textBlock1.Inlines.Add(new Run(", and is geared specifically at integrating "));
textBlock1.Inlines.Add(new Italic(new Run("small")));
textBlock1.Inlines.Add(new Run(" portions of flow content into a UI."));
Which although doesn't change background color, will lead to that if I could make it work ;)
I think in every example of the kind of code I've quoted above, the writer always ends that code with something like this...
this.Content = textBlock1;
And the examples I've seen also always seem to inherit from the Window class. I don't want to do it this way. I want to find my search terms, highlight the given text and allow the bound TextBlock to update itself based on the populated List of type ProductModel.
I've tried changing the type of ProductDescription to a TextBlock, and used the above code to allow my XAML to remain bound directly to it
ie..
PM.ProductDescription = textBlock1;
In this case there was no GUI output at all for the content.
I've also tried straight HTML-like formatting to the string type
ie..
PM.ProductDescription = "<bold>Hello World</bold>";
This gives the literal text output of <bold>Hello World</bold> on the TextBlock control though.
I've also tried changing the type of Binding key from Text to other things in the hope I might work it out, without success.
Any ideas or help would be greatly appreciated, thank you!
Here is a little picture of what I would like to see the program be able to do..

Do I need dependency properties for all basic properties on my user control?

I am currently writing my first user control which would consist of a label and a text box in a stack panel like follows:
<Grid>
<StackPanel Orientation="Horizontal" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Label Content="{Binding Label}" Width="60"></Label>
<TextBox Text="{Binding TextBoxContent}" Width="60"/>
</StackPanel>
</Grid>
This will be most useful to be in a settings page, as it will be reused for several different settings. With each of these settings, I will want to set (at a minimum) the width, height, validation rule and error template properties. As for the text itself, I have already created a dependency property both for the label and the text box (as you can see in my snippet above).
My question is this: Do I need to create a dependency property for all of the properties I just mentioned that I would like to set when I actually use my user control? This seems like redundant work (since they already exist on the text box, basically they would just redirect my user control's property to the text box's property of the same name)? This is even more work if I want to use even more properties on my text box (for example, AcceptsReturn, etc).
The redundant work can be saved if you decide to derive from TextBox rather than UserControl - just think of your control as a "labeled textbox" and all you need to do is derive from TextBox and add the needed dependency properties to accommodate for the label. This of course would not be the case for more complex user controls, but it seems OK in your case.
The downside to this though is that you'll have to take the default control template for TextBox and work with it to add your label, which may be a bit trickier.
Either way, I recommend having a look at the Control Authoring Overview page on MSDN, which is extremely useful when writing your first controls in WPF.

Change text of textblock within a panoramaitem

I need to use two textblock within a single panorama item. I have used a grid to implement this.
Problem is that I need to change the text of the textblock programmatically.
<phone:PanoramaItem Header="Current Status">
<Grid >
<TextBlock x:Name="Spent" Margin="138,0,90,464" FontSize="40"/>
<TextBlock x:Name="Left" Margin="138,50,90,414" FontSize="40"/>
</Grid>
</phone:PanoramaItem>
Saying:
Spent.Text = Convert.ToString(total_spent);
Left.Text = Convert.ToString(total_left);
in the c# file gives an error.
Please tell me how to change the text of the individual textblocks :)
P.S:
I am an absolute beginner and almost completely self taught, so a simple answer will be useful
Thanks
You need to use Text property of the TextBlock to get/set the Text.
From MSDN : TextBlock.Text
Gets or sets the text contents of a TextBlock.
Try This:
Spent.Text = Convert.ToString(total_spent.Text);
Left.Text = Convert.ToString(total_left.Text);

Remove the C# TextBlock inlines elements padding

About TextBlock UIElement in C#, we could add several Run object into it, which will be appended to inlines property. That's one way we show several pieces of text with different format(font, size and etc) in one TextBlock.
My question is: when I add, such as, two Run object into one TextBlock, there exist a padding between each Run object. For example, I add "12" and "34" Run objects, and finally they will be shown as "12 34" in the view. But what I need is they should be connected together as one word - "1234" - without that padding
Is there any setting we can use to prevent this padding?
Instead of
<TextBlock>
<Run Text="12"/>
<Run Text="34"/>
</TextBlock>
write the runs in one line like this
<TextBlock>
<Run Text="12"/><Run Text="34"/>
</TextBlock>
And the space will be gone.

wpf updating text block

I am trying to create some form of updating area in wpf. It needs to be up datable as it will be connected to a live stream of text that will constantly need to be displayed.
The idea is that I will have a stream of data which will comprise of a UserName and Text, this will come in a random times and need to be displayed:
User:Test :: Test:TextData
User:NextTest :: Test:TestData
and so on each item on a new line, so the object needs to be up datable in a scrolling format so the new item will be added to the bottom.
Currently I am using:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel>
<TextBox Margin="5" TextWrapping="Wrap" AcceptsReturn="True" IsReadOnly="True" x:Name="LogDetails"></TextBox>
</StackPanel>
</ScrollViewer>
However this does not really show the data very well, the data is just string based, does anyone know of a better solution?
Thanks
The question is a little bit vague, but here a try:
As an option, why not using TextBlock instead of TextBox, if the text changes automatically?
Caveat: If you want to use the TextBox, don't forget to set the UndoLimit to 0 . Otherwise, you will have a lot of memory consumption, if you change the TextBox contents continously.
<TextBox UndoLimit="0" .../>
If your text is a concattenation of multiple string-elements, create a layout with a grid and use multiple TextBlocks to shown the data more nicely? Maybe there is also some data you can visualize as symbols?
If it is a log, maybe you want to fill a list with strings and set this list as the ItemsSource of an ItemsControl? Through the ItemTemplate-property you can then specify the layout of each item? Use an ObservableCollection<string>, then you only have to add the strings to the collection and the ItemsControl will refresh automatically. You can use ItemsControl, ListBox, ListView for such a log.

Categories

Resources