locked
Trouble RichTextBlock Binding with SplitView RRS feed

  • Question

  • Hi, 

    I have trouble binding RichTextBlock since RichTextBlock binding in Metro is actually not supported, according to following source, 

    http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/de958373-72a5-4987-97be-1f6549ee143e

    But I still need to dynamically adding content into bind list items in SplitView template, but I don't know how to do it. 

    SplitPage.xaml:

    <ListView Grid.Row="1" Grid.RowSpan="2"
        x:Name="itemListView"
        AutomationProperties.AutomationId="ItemsListView"
        AutomationProperties.Name="Items"
        ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
        SelectionChanged="ItemListView_SelectionChanged" 
    />
    
    
    
    <ScrollViewer Visibility="Visible"  
        x:Name="itemDetail"
     AutomationProperties.AutomationId="ItemDetailScrollViewer"
        DataContext="{Binding SelectedItem, ElementName=itemListView}">
        <StackPanel x:Name="RssContentStackPanel">
            <StackPanel x:Name="itemDetailTitlePanel" Orientation="Horizontal">
                 <Image x:Name="itemImage" Source="{Binding Image}" />
                 <StackPanel x:Name="stackPanel">
                     <TextBlock x:Name="itemTitle" Text="{Binding Title}" Style="{StaticResource SubheaderTextStyle}"/>
                     <TextBlock x:Name="itemSubtitle" Text="{Binding Subtitle}" Style="{StaticResource TitleTextStyle}" />
                 </StackPanel>
            </StackPanel>
            <WebView x:Name="VideoViewer" Source="{Binding VideoLink}" MaxHeight="400"/>
            <TextBlock x:Name="RSSContentTextBlock"  Margin="10" Text="{Binding Content}" />
                            
            <!-- RichTextBlock doesn't support binding -->
            <RichTextBlock x:Name="RichRSSContentTextBlock"/>
            <!--<RichEditBox x:Name="RichRSSContentEditBox"/>-->
       </StackPanel>
    
    </ScrollViewer>

    SplitPage.xaml.cs

    // retrieve rss group list from storage
    m_RssItemList = await m_RSSUpdate.RetrieveRSSItemsFromStorageAsync(m_ItemsListFolderName, m_ItemsListFileName);
    
                        if (m_RssItemList != null && m_RssItemList.Count > 0)
                        {
                            NumberOfFeeds.Text = m_RssItemList.Count.ToString() + " Articles";
                            //m_RSSUpdate.DisplayRSSItems(m_RssItemList, m_CurrentRSSDataGroup);
    
                            foreach (var feed in m_RssItemList)
                            {
                                if (feed != null)
                                {
                                    // Assign values from storage
                                    string title = feed.Title;
                                    string publishDate = feed.PublishDate.ToString();
                                    string description = feed.Description;
                                    string ImageLink = "";
                                    if (feed.ImageUri != null)
                                        ImageLink = feed.ImageUri.ToString();
                                    string content = feed.Content;
                                    string link = feed.RSSUri.ToString();
                                    RSSDataGroup RSSGroup = m_CurrentRSSDataGroup;
                                    string webContent = feed.WebContent;
                                    string VideoLink = feed.VideoLink;
    
                                    Paragraph paragraph = new Paragraph();
                                    if (feed.RichText != null)
                                    {
                                        foreach (var para in feed.RichText)
                                        {
                                            // add Rich Text
                                            if (para.text != "")
                                            {
                                                Run paraContent = new Run();
                                                paraContent.Text = para.text;
    
                                                if (para.IsBold)
                                                {
                                                    paraContent.FontWeight = FontWeights.Bold;
                                                }
                                                if (para.IsItalian)
                                                {
                                                    paraContent.FontStyle = FontStyle.Italic;
                                                }
                                                paraContent.Foreground = m_color.Convert("#DE383838");
    
                                                paraContent.FontSize = 24;    
                                        
                                                paragraph.Inlines.Add(paraContent);
                                                paragraph.Inlines.Add(new LineBreak());
                                                paragraph.Inlines.Add(new LineBreak());
                                            }
    
                                    m_RSSData.AddRSSItemtoGroup(RSSGroup, title, title, publishDate, ImageLink, description, content, link, webContent, VideoLink, paragraph);
    
                                    // RichTextBlock
                                    //RichTextBlock RichTextBlock = new RichTextBlock();
                                    RichRSSContentTextBlock.Blocks.Add(paragraph);
                                    //RssContentStackPanel.Children.Add(RichRSSContentTextBlock);
    
                                }
                            }
                        }
    

    m_RSSData.AddRSSItemtoGroup method: it's the method allow binding

            public void AddRSSItemtoGroup(RSSDataGroup Group, string ItemName, string ItemTitle, string ItemSubtitle,
                                      string ImagePath, string ItemDescription, string ItemContent, string Link, string WebContent, string VideoLink, Paragraph paragraph)
            {
                try
                {
                    string Category = Group.Category;
                    Uri VideoLinkUri = null;
                    if (VideoLink != "" && VideoLink != null && VideoLink.Contains("http"))
                    {
                        //Debug.WriteLine("Video link: {0}", VideoLink);
                        VideoLinkUri = new Uri(VideoLink);
                    }
    
                    Group.Items.Add(new RSSDataItem(Group.UniqueId, ItemTitle, ItemSubtitle, ImagePath, ItemDescription, ItemContent, Group, Link, 0, Category, WebContent, VideoLinkUri, paragraph));
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Error: AddRSSItemtoGroup - {0}", ex.StackTrace);
                }
            }
    

    Again, I can't simply "new" a item in list, since all the items are based on binding, but not being created a new instance. 

    Thank you,


    Jerry

    Tuesday, August 21, 2012 8:37 AM

Answers

  • Sure. I don't know if this is the actual solution to the problem, but using the code below I was able to (indirectly) bind a Paragraph to a RichTextBlock by wrapping it into a UserControl and binding to a custom property on that UserControl. You should then use the UserControl in your item template instead of the RichTextBlock directly. As an example I created a custom property on the UserControl of type Block, but you could also pass the raw data to the property, do the ParaGraph parsing there and then assign it to the RichTextBlock.

    <Page
        x:Class="TestRichEdit.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestRichEdit"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        
        <Page.Resources>
            <ResourceDictionary>
                <local:RichEditBoxContainerUserControlData x:Key="RichEditBoxContainerUserControlData"></local:RichEditBoxContainerUserControlData>
            </ResourceDictionary>
        </Page.Resources>
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <local:RichEditBoxContainerUserControl Name="richEditBoxContainerUserControl" DataContext="{StaticResource RichEditBoxContainerUserControlData}"
                                                   Paragraph="{Binding ParagraphData}">
    
            </local:RichEditBoxContainerUserControl>
        </Grid>
    </Page>
    ---
    <UserControl
        x:Class="TestRichEdit.RichEditBoxContainerUserControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestRichEdit"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
        
        <Grid>
            <RichTextBlock Name="richTextBlock" FontSize="40"></RichTextBlock>
        </Grid>
    </UserControl>
    ---
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Documents;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    
    // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
    
    namespace TestRichEdit
    {
        public sealed partial class RichEditBoxContainerUserControl : UserControl
        {
            public static readonly DependencyProperty ParagraphDependencyProperty = DependencyProperty.Register("Paragraph", typeof(Block),
                typeof(RichEditBoxContainerUserControl), new PropertyMetadata(null, RichEditBoxContainerUserControl.ParagraphPropertyChangedCallback));
                
            private static void ParagraphPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                ((RichEditBoxContainerUserControl)d).Paragraph = (Block)e.NewValue;
            }
    
            public RichEditBoxContainerUserControl()
            {
                this.InitializeComponent();
            }
    
            public Block Paragraph
            {
                get
                {
                    if (richTextBlock.Blocks.Count > 0)
                    {
                        return richTextBlock.Blocks[0];
                    }
    
                    return null;
                }
                set
                {
                    richTextBlock.Blocks.Clear();
                    richTextBlock.Blocks.Add(value);
                }
            }
        }
    }
    ---
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.UI.Xaml.Documents;
    
    namespace TestRichEdit
    {
        public class RichEditBoxContainerUserControlData
        {
            public RichEditBoxContainerUserControlData()
            {
    
            }
    
            public Block ParagraphData
            {
                get
                {
                    Paragraph para = new Paragraph();
                    Run paraContent = new Run();
                    paraContent.Text = "Dummy Text";
    
                    para.Inlines.Add(paraContent);
    
                    return para;
                }
            }
        }
    }
    
    Is this something you can use?

    • Edited by Paul Dentener Saturday, August 25, 2012 6:36 AM
    • Proposed as answer by Aaron Xue Wednesday, August 29, 2012 2:04 AM
    • Marked as answer by Jerrywu12 Friday, August 31, 2012 2:18 AM
    Saturday, August 25, 2012 6:35 AM

All replies

  • As an idea, what if you would wrap the RichTextBlock in a custom control with a custom dependency property and set that property using a binding to a RSSDataItem property? In the property setter / dependency property callback of the property you could parse the value into a Paragraph and push it into the RichTextBlock which is a child control of the custom control.


    Tuesday, August 21, 2012 12:42 PM
  • Hi Paul,

    Is it possible to create binding to custom control if it is inherited from RichTextBlock?

    Do you mind show me how to do it?

    Thank you,


    Jerry

    Friday, August 24, 2012 4:07 AM
  • Sure. I don't know if this is the actual solution to the problem, but using the code below I was able to (indirectly) bind a Paragraph to a RichTextBlock by wrapping it into a UserControl and binding to a custom property on that UserControl. You should then use the UserControl in your item template instead of the RichTextBlock directly. As an example I created a custom property on the UserControl of type Block, but you could also pass the raw data to the property, do the ParaGraph parsing there and then assign it to the RichTextBlock.

    <Page
        x:Class="TestRichEdit.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestRichEdit"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        
        <Page.Resources>
            <ResourceDictionary>
                <local:RichEditBoxContainerUserControlData x:Key="RichEditBoxContainerUserControlData"></local:RichEditBoxContainerUserControlData>
            </ResourceDictionary>
        </Page.Resources>
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <local:RichEditBoxContainerUserControl Name="richEditBoxContainerUserControl" DataContext="{StaticResource RichEditBoxContainerUserControlData}"
                                                   Paragraph="{Binding ParagraphData}">
    
            </local:RichEditBoxContainerUserControl>
        </Grid>
    </Page>
    ---
    <UserControl
        x:Class="TestRichEdit.RichEditBoxContainerUserControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestRichEdit"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
        
        <Grid>
            <RichTextBlock Name="richTextBlock" FontSize="40"></RichTextBlock>
        </Grid>
    </UserControl>
    ---
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Documents;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    
    // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
    
    namespace TestRichEdit
    {
        public sealed partial class RichEditBoxContainerUserControl : UserControl
        {
            public static readonly DependencyProperty ParagraphDependencyProperty = DependencyProperty.Register("Paragraph", typeof(Block),
                typeof(RichEditBoxContainerUserControl), new PropertyMetadata(null, RichEditBoxContainerUserControl.ParagraphPropertyChangedCallback));
                
            private static void ParagraphPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                ((RichEditBoxContainerUserControl)d).Paragraph = (Block)e.NewValue;
            }
    
            public RichEditBoxContainerUserControl()
            {
                this.InitializeComponent();
            }
    
            public Block Paragraph
            {
                get
                {
                    if (richTextBlock.Blocks.Count > 0)
                    {
                        return richTextBlock.Blocks[0];
                    }
    
                    return null;
                }
                set
                {
                    richTextBlock.Blocks.Clear();
                    richTextBlock.Blocks.Add(value);
                }
            }
        }
    }
    ---
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.UI.Xaml.Documents;
    
    namespace TestRichEdit
    {
        public class RichEditBoxContainerUserControlData
        {
            public RichEditBoxContainerUserControlData()
            {
    
            }
    
            public Block ParagraphData
            {
                get
                {
                    Paragraph para = new Paragraph();
                    Run paraContent = new Run();
                    paraContent.Text = "Dummy Text";
    
                    para.Inlines.Add(paraContent);
    
                    return para;
                }
            }
        }
    }
    
    Is this something you can use?

    • Edited by Paul Dentener Saturday, August 25, 2012 6:36 AM
    • Proposed as answer by Aaron Xue Wednesday, August 29, 2012 2:04 AM
    • Marked as answer by Jerrywu12 Friday, August 31, 2012 2:18 AM
    Saturday, August 25, 2012 6:35 AM
  • Hey Paul, I finally find a chance to try your method out and fix the problem of binding.

    However, the customized UserControl doesn't preserve the properties of RichEditBox, is it possible to inherited RichEditBox instead of a UserControl?

    Thanks a lot!


    Jerry




    • Edited by Jerrywu12 Tuesday, September 11, 2012 7:20 AM
    Tuesday, September 11, 2012 7:08 AM