locked
Binding to RichTextBlock RRS feed

  • Question

  • From a look at the documentation (which is a bit thin) and a variety of google searches, it would seem that there is no easy way of binding rich text content to a RichTextBlock.

    There are a number of use cases I have for this - a search results display with search terms marked up (like Google, sorry bing), a document drawn from a database and others.  I am aware of methods using a value converter to add a series of paragraphs to the Blocks property (which I've done on WPF), but it would be nice to think I could use a text string metro/XAML RTF language and bind that to a 'Text' Property and that would be it.

    Is this really the case?  Do I only have the choices of in XAML rich text or manually (programmatically!)  to manage the contents of the Blocks property?

    Hoping I'm wrong...

    Iain


    Iain Downs

    Wednesday, June 6, 2012 3:51 PM

Answers

  • I've not found a way of parsing the text as such.  This is mainly because there doesn't seem to be a 'BlockCollection' declared in the xaml xml - it's a code only thing.  I'd be happy to be proven wrong on this.  Of course you could write a parser - which isn't terribly difficult - just a waste of time.

    What I have done is this.

    Use a content control in the markup with a Value converter

    <ContentControl Content="{Binding Path=Snippet, Converter={StaticResource RtFToBlocks}}">
    </ContentControl> 

    The RTF XAML needs to look like this

    <RichTextBlock xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'><Paragraph><Bold>Fearful</Bold> of all things, Fred...</Paragraph></RichTextBlock>

    and the value converter

            public object Convert(object value, Type targetType, object parameter, string language)
            {
                string rtfText = (string)value;
                object blocksObj = XamlReader.Load(rtfText);
                return (RichTextBlock)blocksObj;
            }
    

    So when the items source dataobject is bound, the value converter is called, it creates an RtfTextBlock from the Rtf text (with the RtfTextBlock object patched around it) and that's it.

    Of course this is a pretty nasty way of doing this and I haven't seen what happens when I try and use it with the RichTextColumns class but it's a potential workaround.

    Iain


    Iain Downs

    Thursday, June 7, 2012 3:32 PM
  • You guys bring up good points. They touch on many of the tougher decisions made by the text team during the Win8 product cycle as well as some painful feature cuts. We realize that changing content models between similar products (WPF, Silverlight, Xaml) is frustrating and reduces the amount of code devs can reuse. We also understand that having different content models between controls within one framework (RichTextBlock-Xaml content and RichEditBox-RTF content) requires extra work on you guy’s part if you want to move info from one control to another.

    We decided to build RichEditBox for a bunch of reasons. RichEdit is a much more mature editing codebase than either of WPF or Silverlight editing controls. It supports important features and a rich API set (everything exposed by RichEditBox.Document) that would have taken our devs years to create and stabilize. RichEdit is also used in many other places in Windows so the Xaml framework is more consistent with the system as a whole. Hopefully this is a good foundation that we can build on, fixing gaps as we go along (eg. Xaml <-> RTF converter).

     A missing bindable Xaml property on RichTextBlock is something we would have liked to include but did not have time to implement. This is something that’s definitely on our feature list for VNext. In the mean time you guys could try the converter workaround IainDowns2 mentioned. Personally I just take a Xaml string, load it into XMLDocument, and then programmatically create elements for each node of the Xaml. The Xaml text object model doesn’t have too many types so this mini parser isn’t too hard to write (but it’s code on really shouldn’t have to create).

    Stefan, it sounds like you used read-only RichTextBlocks to flow text on the Phone. If this is correct you should check out RichTextBlock.OverflowContentTarget and the RichTextBlockOverflow class. This lets you create a chain of linked text containers. You’ll still have to get all of the Xaml content into the first RichTextBlock, but the framework will take care of flowing the text across the different elements. This should make your life easier by freeing you from stuffing text into each read-only RichTextBox.

    Thursday, July 19, 2012 4:33 PM

All replies

  • From a look at the documentation (which is a bit thin) and a variety of google searches, it would seem that there is no easy way of binding rich text content to a RichTextBlock.

    There are a number of use cases I have for this - a search results display with search terms marked up (like Google, sorry bing), a document drawn from a database and others.  I am aware of methods using a value converter to add a series of paragraphs to the Blocks property (which I've done on WPF), but it would be nice to think I could use a text string metro/XAML RTF language and bind that to a 'Text' Property and that would be it.

    Is this really the case?  Do I only have the choices of in XAML rich text or manually (programmatically!)  to manage the contents of the Blocks property?

    Hoping I'm wrong...

    Iain


    Iain Downs

    • Merged by Min ZhuMember Monday, June 18, 2012 7:15 AM duplicated
    Wednesday, June 6, 2012 3:46 PM
  • You could take XamlReader to load a xaml formated string an add this as Content of the RichTextBlox. But I would also say that there is no easy way.

    lh

    Wednesday, June 6, 2012 8:26 PM
  • Iain,

    Unfortunately, you don't have any options other than manually (or parsing xaml, but I haven't confirmed that works yet) creating the paragraphs.  On the phone they did this correctly, you could set and get the Xaml property, but they haven't done that in WinRT, making life much more complicated.

    ...Stefan


    • Edited by StefanOlson Wednesday, June 6, 2012 9:14 PM
    Wednesday, June 6, 2012 9:14 PM
  • Stefan - can you post how this is supported on the phone? RichText_Block_ never has supported a XAML property, but RichText_Box_ on the phone does. Just trying to make sure I understand the request.

    -mark
    Program Manager
    Microsoft
    This post is provided "as-is"
    Wednesday, June 6, 2012 9:30 PM
  • Mark,

    You are right, I am using RichTextBox, read only, on the phone.  Have never investigated RichTextBlock.  Basically I've got content that I convert from Html to Xaml and then load them into  a stack panel of RichTextBoxes (to work around the 2000 pixel height limit of a single control, splitting them every paragraph or line break!).  I will want to do the same thing on WinRT, but it's going to be somewhat more complicated because I'm assuming that the Html->Xaml converter is going to have to output a RichTextBlock and then the content inside it.  Hopefully I'm going to be able to use XamlReader.  Too busy dealing with other things to actually prototype it up at the moment though.  It might work okay, but it's just one of those things that until I have tested it, I'm not going to be confident that it will work.  As it stands it definitely won't work as well as it does on the phone, because there are no support for hyperlinks within the RichTextBlock.  Hyperlink buttons are not going to wrap and therefore is going to look pretty stupid if the hyperlink is longer than will fit on one line.

    I still remain unclear why RichTextBox wasn't implemented in WinRT - we have a third implementation in three different XAML frameworks - RichTextBox in WPF that uses flow documents and is incompatible with RichTextBox on Silverlight that uses a cut down Section based document and RichEditBox,  which uses a completely different system, that I haven't got my head around yet because I haven't had time.

    ...Stefan

    Wednesday, June 6, 2012 9:47 PM
  • Hi Iain,

    If you want to work with RTF then look at the RichEditBox rather than the RichTextBlock control. It's still not directly bindable, but it's one call to set the text to your RTF string. It shouldn't be hard to create a wrapper class to provide a bindable property.

    --Rob

    Thursday, June 7, 2012 3:52 AM
    Moderator
  • I seem to have double entered this - the next post has more responses so I will continue in that one!

    Iain Downs

    Thursday, June 7, 2012 3:24 PM
  • I've not found a way of parsing the text as such.  This is mainly because there doesn't seem to be a 'BlockCollection' declared in the xaml xml - it's a code only thing.  I'd be happy to be proven wrong on this.  Of course you could write a parser - which isn't terribly difficult - just a waste of time.

    What I have done is this.

    Use a content control in the markup with a Value converter

    <ContentControl Content="{Binding Path=Snippet, Converter={StaticResource RtFToBlocks}}">
    </ContentControl> 

    The RTF XAML needs to look like this

    <RichTextBlock xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'><Paragraph><Bold>Fearful</Bold> of all things, Fred...</Paragraph></RichTextBlock>

    and the value converter

            public object Convert(object value, Type targetType, object parameter, string language)
            {
                string rtfText = (string)value;
                object blocksObj = XamlReader.Load(rtfText);
                return (RichTextBlock)blocksObj;
            }
    

    So when the items source dataobject is bound, the value converter is called, it creates an RtfTextBlock from the Rtf text (with the RtfTextBlock object patched around it) and that's it.

    Of course this is a pretty nasty way of doing this and I haven't seen what happens when I try and use it with the RichTextColumns class but it's a potential workaround.

    Iain


    Iain Downs

    Thursday, June 7, 2012 3:32 PM
  • You guys bring up good points. They touch on many of the tougher decisions made by the text team during the Win8 product cycle as well as some painful feature cuts. We realize that changing content models between similar products (WPF, Silverlight, Xaml) is frustrating and reduces the amount of code devs can reuse. We also understand that having different content models between controls within one framework (RichTextBlock-Xaml content and RichEditBox-RTF content) requires extra work on you guy’s part if you want to move info from one control to another.

    We decided to build RichEditBox for a bunch of reasons. RichEdit is a much more mature editing codebase than either of WPF or Silverlight editing controls. It supports important features and a rich API set (everything exposed by RichEditBox.Document) that would have taken our devs years to create and stabilize. RichEdit is also used in many other places in Windows so the Xaml framework is more consistent with the system as a whole. Hopefully this is a good foundation that we can build on, fixing gaps as we go along (eg. Xaml <-> RTF converter).

     A missing bindable Xaml property on RichTextBlock is something we would have liked to include but did not have time to implement. This is something that’s definitely on our feature list for VNext. In the mean time you guys could try the converter workaround IainDowns2 mentioned. Personally I just take a Xaml string, load it into XMLDocument, and then programmatically create elements for each node of the Xaml. The Xaml text object model doesn’t have too many types so this mini parser isn’t too hard to write (but it’s code on really shouldn’t have to create).

    Stefan, it sounds like you used read-only RichTextBlocks to flow text on the Phone. If this is correct you should check out RichTextBlock.OverflowContentTarget and the RichTextBlockOverflow class. This lets you create a chain of linked text containers. You’ll still have to get all of the Xaml content into the first RichTextBlock, but the framework will take care of flowing the text across the different elements. This should make your life easier by freeing you from stuffing text into each read-only RichTextBox.

    Thursday, July 19, 2012 4:33 PM
  • Sorry to revive an old-ish thread. But what happens if the results you want to stuff into the RichTextBlock is, say, the results of a search which may include XML or HTML tags? It looks to me like that may create serious problems with Iain Downs solution. But I clearly don't have the same grasp of what's going on as some of you do.

    What other workaround are there that could potentially handle that? I have tried to find some examples of how to fill in a rich text block in the codebehind, but they are hard to come by or overkill.

    Thursday, August 9, 2012 4:38 PM
  • If you have non Xaml Rtf content then you pretty much have to parse it and construct the text model adding it to the RichTextBlock Blocks property (or whatever it's called).  That's pretty much what Chipalo proposes.

    If your good with Xslt you could create a transform from your custom XML/HTML content to the Xaml you need.  Which simply changes the technology you use, rather than the complexity.

    Good luck!

    Iain


    Iain Downs

    Thursday, August 9, 2012 6:05 PM
  • Has anyone actually implemented the IainDowns2 technique?

    When I tried it, the content that was inserted was "Windows.UI.XAML.Controls.RichTextBlock" which I believe is just the ToString() of the object that was returned from the converter.

    Given that the TargetType passed to the converter is String, this behavior would not be hard to understand.

    Maybe I did something wrong, or maybe I'm still looking for the best technique to programmatically add formatted RichTextBlock content.

    Brian

    Thursday, November 29, 2012 3:36 AM
  • Well, I have.  So I'm happy to claim it works!

    If you post the XAML and convertor code then I can perhaps see what's not working.  You specify that the TargetType is string which I would not expect and does not match the code snippet I provided.

    Let me know.

    Iain


    Iain Downs


    • Edited by IainDowns2 Thursday, November 29, 2012 7:26 PM spelling
    Thursday, November 29, 2012 7:32 AM
  • I see what I did wrong. The trick is binding to the right type in the XAML. I'm trying to insert rich text into the XAML generated by VS for the ItemDetailPage.

    If it helps others here's where I do the binding:

    <common:LayoutAwarePage
        xmlns:data="using:GridApp3Page.Data">
        <Page.Resources>
            <data:XamlBlocks x:Key="XamlBlocks" />
        </Page.Resources>
        <UserControl>
            <ScrollViewer>
                <StackPanel Orientation="Horizontal">
                    <common:RichTextColumns 
                        x:Name="richTextIntroduction" 
                        Margin="117,0,117,47" 
                        RichTextContent="{
                            Binding Introduction, 
                            Converter={
                               StaticResource 
                               XamlBlocks}}">

    I was pleasantly surprised to find that the elements converted via my XamlBlocks method could even include references to {Resources} in the containing XAML. For me, that means the inserted elements can be styled externally.
    Wednesday, December 5, 2012 4:20 PM
  • Hello,

    I'm trying to use that tip within a RichTextColumns.

    If I want a "basic" text I use the following XAML code :

    <Paragraph Margin="0,0,0,30" LineStackingStrategy="MaxHeight">
        <Run FontWeight="SemiLight" Text="{Binding Content}" />
    </Paragraph>

    Everything is perfect, my text appears in multi-column.

    But as it could be a lot better with some text formatting I have implemented IainDowns workaround.

    <Paragraph Margin="0,0,0,30" LineStackingStrategy="MaxHeight">
        <InlineUIContainer>
            <ContentControl Content="{Binding Path=Content, Converter={StaticResource RtfToBlocks}}" />
        </InlineUIContainer>
    </Paragraph>

    The formatting of the text is perfect. Thanks Iain.

    My problem is that at that the text overflow no more jump to a new column.

    I suspect that it's because I'm inserting a RichTextBlock into a Paragraph. By doing so my paragraph is probably seen as a whole block.

    Has anyone tryed to do that ?

    Kind regards,

    Pascal

    Wednesday, December 12, 2012 3:19 PM
  • If you have troubles with multi-column don't do as I :-) Bind your Xaml text directly to the RichTextColumns instead of placing it in a Paragraph :

    <common:RichTextColumns x:Name="richTextColumns" RichTextContent="{Binding Path=Content, Converter={StaticResource RtFToBlocks}}">
    Pascal

    Friday, December 14, 2012 7:22 AM
  • You guys bring up good points. They touch on many of the tougher decisions made by the text team during the Win8 product cycle as well as some painful feature cuts.

    We say - yeah it is good that you understand but you are killing the devs trust as we speak. You are not getting much business from children with all the dynamic framework or WinRT javascript apps but you are loosing hardcore professionals trust.

    Here is the solution. Fire Sinofski. He delivered now he can go. Bring the devs back in focus. Amend the bullstuff he did with Silverlight.

    Keep focus on creating future technologies - this is what you do best.

    You suck when it comes to tactical short lived decisions and cuts. So concentrate on what you do best.

    Leave Apple alone. Nobody can create the same hipe twice.

    Compete with Google. They are just two big boys. (I fail to understand why you havent figured a recipe for successful search engine by now).

    Windows 8 can very well be a replacement OS for majority of mobile devices so keep improving it in every sence - it is your future cashflow.

    Go with money. Invest money (instead of wasting it on creating dead products because of petty politics p00) into something which makes money to others like content delivery (movies music etc). 

    Stay alive.... What for christ sake we are supposed to do if you screw up? learn the bl00dy Java??

    Saturday, January 19, 2013 11:37 AM


  • I have several questions.

    1) Where did you place the convert method?
    2) Why is the convert method called "Convert" yet it is referenced "StaticResource RtFToBlocks?"
    3) I placed the convert in the associated .cs file of the items detail page but I don't know how to reference it in the xaml. What should I do?


    Monday, April 1, 2013 7:09 PM
  • You need to read up on Value Convertors.

    You would put the Convert method in a class which implemented IValueConvertor.

    You would reference the class as a static resource in your Xaml file.

    Should be easy enough to find the docs with Google.

    Iain


    Iain Downs

    Monday, April 1, 2013 8:58 PM
  • Hello everyone,

    I haven't read completely this discussion.

    Check out this one if this will help to you guys.

    I think If we use below approach  then we can use some binding features.


                        if (paragraph != null)
                        {
                            TextBlock textBlock = new TextBlock();
                            Run run = new Run();
                            Binding myBinding = new Binding() { Path = new PropertyPath("FirstName") };
                            myBinding.Source = YourSOurce// should be changed according to your need 
                            textBlock.SetBinding(TextBlock.TextProperty, myBinding);
                            run.Text = textBlock.Text;
                            run.FontStyle = Windows.UI.Text.FontStyle.Italic;
                            paragraph.Inlines.Add(run);
                        }




    Vote As Helpful, Propose As Answer, or Mark As Answer
    MCSD | MCP
    View my MCP Certifications



    Thursday, May 23, 2013 1:47 PM