Hi Telerik team,
We are evaluating your RichTextBox and MailMerge functionality in order to display read-only, mailmerged views.
In order to create the RadDocument we are using the following sequence:
RichTextBox.Document = document;
RichTextBox.ChangeAllFieldsDisplayMode(FieldDisplayMode.Result); // first GetResultFragment call
RichTextBox.PreviewFirstMailMergeDataRecord(); // second GetResultFragment call
The GetResultFragment is called twice during this process.
On the first call the FieldProperties like PropertyPath, TextAfterIfNotEmpty and TextBeforeIfNotEmpty are set to the values according to our xaml document source.
On the second call the FieldProperties are null and subsequently the Document is not displayed correct.
Why are the FieldProperties reset, or is something wrong with the Document initialization process?
Thank you in advance,
Wolfgang
3 Answers, 1 is accepted
Could you explain in some detail why are you calling both methods, when the two methods generally do the same?
We may be able to assist you better if you attach your project or a mock-up that includes the custom merge fields functionality. In order to do so, however, you would need to open a support ticket, as only image files are allowed in forums.
Iva Toteva
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
Even i am facing the same issue.
I have extended MergeField class to create my custom merge field class with multiple properties which i can preserve in xaml file whiel exporting.
My GetResultFragment is called twice and in second call the custom property DateFormat is null so finally my resulted value is displayed wrong in editor.
public class CustomDateField : MergeField
{
private const string CustomFieldName = "CustomDateField";
static CustomDateField()
{
CodeBasedFieldFactory.RegisterFieldType(CustomDateField.CustomFieldName, () => { return new CustomDateField(); });
}
[XamlSerializable]
public string DateFormat { get; set; }
public override Field CreateInstance()
{
return new CustomDateField();
}
public override string FieldTypeName
{
get
{
return CustomDateField.CustomFieldName;
}
}
public override void CopyPropertiesFrom(Field fromField)
{
CustomDateField mergeField = fromField as CustomDateField;
if (mergeField != null)
{
this.DateFormat = mergeField.DateFormat;
}
base.CopyPropertiesFrom(fromField);
}
protected override DocumentFragment GetResultFragment()
{
try
{
var data = this.Document.MailMergeDataSource.CurrentItem as IDictionary<string, Object>;
if (data == null)
{
return null;
}
else
{
object outputvalue = null;
data.TryGetValue(this.PropertyPath, out outputvalue);
if (outputvalue != null)
{
string date = Convert.ToDateTime(outputvalue).ToString(this.DateFormat);
RadDocument document = new RadDocument();
Section section = new Section();
Paragraph paragraph = new Paragraph();
Span span = new Span(date);
paragraph.Inlines.Add(span);
section.Blocks.Add(paragraph);
document.Sections.Add(section);
return new DocumentFragment(document);
}
}
}
catch (Exception ex)
{
}
return null;
}
}
You need to modify the CustomDateField class in order to support a custom property. What needs to be done is adding a switch and an override to the BuildCodeOverride() method where the custom property should be mapped to the switch. For your convenience, I have modified your code:
public class CustomDateField : MergeField{ private const string CustomFieldName = "CustomDateField"; private static readonly string DateFormatSwitch = @"\df"; // unique for the entire set of mail merge field switches. private readonly FieldProperty dateFormat; public static readonly FieldPropertyDefinition DateFormatDefinition = new FieldPropertyDefinition("DateFormat"); static CustomDateField() { CodeBasedFieldFactory.RegisterFieldType(CustomDateField.CustomFieldName, () => { return new CustomDateField(); }); } public CustomDateField() { this.dateFormat = new FieldProperty(this, CustomDateField.DateFormatDefinition); } [XamlSerializable] public string DateFormat { get { return this.dateFormat.GetValue(); } set { if (!this.dateFormat.IsNestedField && this.dateFormat.GetValue() == value) { return; } this.dateFormat.SetValue(value); this.InvalidateCode(); } } public override Field CreateInstance() { return new CustomDateField(); } public override string FieldTypeName { get { return CustomDateField.CustomFieldName; } } public override void CopyPropertiesFrom(Field fromField) { CustomDateField mergeField = fromField as CustomDateField; if (mergeField != null) { this.DateFormat = mergeField.DateFormat; } base.CopyPropertiesFrom(fromField); } protected override void BuildCodeOverride() { base.BuildCodeOverride(); this.CodeBuilder.AddSwitch(CustomDateField.DateFormatSwitch, this.dateFormat); } protected override void CopyPropertiesFromCodeExpression(FieldCodeExpression fieldCodeExpression) { base.CopyPropertiesFromCodeExpression(fieldCodeExpression); FieldSwitchNode fieldSwitchNode = fieldCodeExpression.GetFieldSwitch(DateFormatSwitch); this.dateFormat.SetValue(fieldSwitchNode.FieldArgumentNode); } protected override DocumentFragment GetResultFragment() { try { var data = this.Document.MailMergeDataSource.CurrentItem as IDictionary<string, Object>; if (data == null) { //return null; //This return value is not allowed. It may crash the application. return new DocumentFragment(new RadDocument()); } else { object outputvalue = data; data.TryGetValue(this.PropertyPath, out outputvalue); if (outputvalue != null) { string date = Convert.ToDateTime(outputvalue).ToString(this.DateFormat); RadDocument document = new RadDocument(); Section section = new Section(); Paragraph paragraph = new Paragraph(); Span span = new Span(date); paragraph.Inlines.Add(span); section.Blocks.Add(paragraph); document.Sections.Add(section); return new DocumentFragment(document); } } } catch (Exception ex) { } //return null; //This return value is not allowed. It may crash the application. return new DocumentFragment(new RadDocument()); }}If you need more information how to create a custom field, please read our Custom Field help article.
Regards,
Boyko
Telerik