Issue with RadRichTextBox and Merge method of RadFlowDocument

5 posts, 0 answers
  1. Ricky
    Ricky avatar
    3 posts
    Member since:
    Oct 2014

    Posted 10 Dec 2014 Link to this post

    My application stores many small snippets of information in docx format. The individual information snippets must be stored internally in a way that can be easily accessed as a byte array (IList<byte> and ToArray() works). Another requirement is that the application be able to collate snippets into a document which can be exported.

    I am able to use a DocxFormatProvider to import individual snippets to a RadFlowDocument, and can then use the Merge method of RadFlowDocument as necessary to achieve the desired result.

    However, I am unable to import a snippet that is the result of the Merge method, if that snippet has been edited from inside a RadRichTextBox. Below is code to reproduce the issue.

    MainWindow.xaml:
    <Window x:Class="TelerikDocxManipulationTest.MainWindow"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
                    Title="MainWindow" Height="800" Width="1000">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
     
            <telerik:DocxDataProvider x:Name="DocxDataProvider"
                                      RichTextBox="{Binding ElementName=DataInput}"
                                      Docx="{Binding Data, Mode=TwoWay}">
            </telerik:DocxDataProvider>
     
            <StackPanel Orientation="Horizontal">
                <Button Grid.Column="1" Width="100" Margin="10,0,0,0" Click="Import">
                    <TextBlock>
                        Import
                    </TextBlock>
                </Button>
                <Button Grid.Column="1" Width="100" Margin="10,0,0,0" Click="Merge">
                    <TextBlock>
                        Merge
                    </TextBlock>
                </Button>
                <Button Grid.Column="1" Width="100" Margin="10,0,0,0" Click="Export">
                    <TextBlock>
                        Export
                    </TextBlock>
                </Button>
            </StackPanel>
             
            <telerik:RadRichTextBox x:Name="DataInput"
                                    Grid.Row="1"
                                    IsSpellCheckingEnabled="False"
                                    HorizontalScrollBarVisibility="Hidden"
                                    VerticalScrollBarVisibility="Visible"
                                    LayoutMode="Paged"/>
        </Grid>
    </Window>

    MainWindow.xaml.cs:
    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Linq;
    using System.Windows;
    using Telerik.Windows.Documents.Flow.FormatProviders.Docx;
    using Telerik.Windows.Documents.Flow.Model;
    using Telerik.Windows.Documents.Flow.Model.Collections;
     
    namespace TelerikDocxManipulationTest
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            public MainWindow()
            {
                InitializeComponent();
                DataContext = this;
            }
     
            /// <summary>
            /// Telerik DocxFormatProvider
            /// </summary>
            private DocxFormatProvider provider = new DocxFormatProvider();
     
            /// <summary>
            /// The binary data for the docx file
            /// </summary>
            private IList<byte> mData = new List<byte>();
            public IList<byte> Data
            {
                get
                {
                    return mData;
                }
                set
                {
                    mData = value;
                    OnPropertyChanged("Data");
                }
            }
     
            /// <summary>
            /// Import a docx file from disk
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Import(object sender, RoutedEventArgs e)
            {
                OpenFileDialog dialog = new OpenFileDialog();
                dialog.Filter = "docx files (*.docx)|*.docx";
                dialog.RestoreDirectory = true;
     
                if (dialog.ShowDialog() == true)
                {
                    try
                    {
                        Data = File.ReadAllBytes(dialog.FileName).ToList();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
     
            /// <summary>
            /// Merge the current document with a docx document from disk
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Merge(object sender, RoutedEventArgs e)
            {
                OpenFileDialog dialog = new OpenFileDialog();
                dialog.Filter = "docx files (*.docx)|*.docx";
                dialog.RestoreDirectory = true;
     
                if (dialog.ShowDialog() == true)
                {
                    try
                    {
                        RadFlowDocument existingDocument = provider.Import(Data.ToArray());
                        RadFlowDocument mergeDocument = provider.Import(dialog.OpenFile());
     
                        existingDocument.Merge(mergeDocument);
     
                        Data = provider.Export(existingDocument).ToList();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
     
            /// <summary>
            /// Export the current file data to disk
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Export(object sender, RoutedEventArgs e)
            {
                SaveFileDialog dialog = new SaveFileDialog();
                dialog.DefaultExt = "docx";
                dialog.Filter = "docx files (*.docx)|*.docx";
                dialog.RestoreDirectory = true;
     
                if (dialog.ShowDialog() == true)
                {
                    using (Stream output = dialog.OpenFile())
                    {
                        try
                        {
                            output.Write(Data.ToArray(), 0, Data.Count);
                            MessageBox.Show("Document exported.");
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                    }
                }
            }
     
     
            #region INotifiedProperty Block
            public event PropertyChangedEventHandler PropertyChanged;
     
            protected void OnPropertyChanged(string propertyName)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
     
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            #endregion
        }
    }

    Here are the steps to follow to reproduce the issue:

    1) Open a docx file by clicking "Import"
    2) Append a second docx file by clicking "Merge"
    3) Edit the resulting document inside the RTB.
    4) Append a third docx file by clicking "Merge"

    An exception will be thrown at line 86 in MainWindow.xaml.cs by:
    RadFlowDocument existingDocument = provider.Import(Data.ToArray());

    The exception is:
    "The given key was not present in the dictionary."



    Also, I would be very grateful for any information about how I might remove the line break inserted between documents by the Merge method. When merging documents, there does not appear to be any line break in the RadRichTextBox. However, after clicking "Export" and saving the document, line breaks appear between the merged documents in Word.
  2. Petya
    Admin
    Petya avatar
    975 posts

    Posted 15 Dec 2014 Link to this post

    Hi Ricky,

    I tried reproducing the issue you are experiencing but to no avail. Attached is the test project I created based on the snippets you sent us along with three test documents which I used to execute the steps you listed. I'm not observing an exception, so I presume this is related to the content of your documents. Could you please open a support ticket and send us some of the files? This will help us investigate the issue on our end and address it accordingly.

    As to your question concerning breaks, the merging functionality of documents is intended to add the contents of separate documents to separate sections. The reason RadRichTextBox does not show them separately is an issue in the control that I logged for further revision.

    However, if you want to change the behavior you can simply change the type of the sections just before the export. This will still add them to the document, but showing it will allow the text to flow on the same page.
        if (dialog.ShowDialog() == true)
        {
            using (Stream output = dialog.OpenFile())
            {
                try
                {
                    RadFlowDocument existingDocument = provider.Import(Data.ToArray());
                    foreach (var section in existingDocument.Sections)
                    {
                        section.SectionType = SectionType.Continuous;
                    }
     
                    provider.Export(existingDocument, output);
                    MessageBox.Show("Document exported.");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }

    I hope this is useful. We are looking forward to hearing from you in regard to the observed error.

    Regards,
    Petya
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Ricky
    Ricky avatar
    3 posts
    Member since:
    Oct 2014

    Posted 15 Dec 2014 in reply to Petya Link to this post

    I was able to reproduce the issue using this project and the test files contained within the project. Here is a video:

    http://tinypic.com/r/1424ia1/8

    I was missing some library references which prevented the project from compiling at first. I ran the upgrade wizard (Telerik -> UI for WPF -> Upgrade Wizard in Visual Studio 2013), which resolved the issue. Besides that I made no alterations.
  5. Petya
    Admin
    Petya avatar
    975 posts

    Posted 17 Dec 2014 Link to this post

    Hi Ricky,

    I was able to replicate the behavior with one of the older versions of the suite. Can you please upgrade your project to the most recent 2013 Q3 SP1 (2014.3 1202) release? The error does not seem to be occurring there.

    Let me know how it goes.

    Regards,
    Petya
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  6. Ricky
    Ricky avatar
    3 posts
    Member since:
    Oct 2014

    Posted 18 Dec 2014 in reply to Petya Link to this post

    Thank you Petya, upgrading has fixed the issue.
Back to Top
UI for WPF is Visual Studio 2017 Ready