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:
MainWindow.xaml.cs:
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.
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: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.