Load and Save Documents
An editor becomes useful once users can open their documents and save their work. TextControl brings the Open and Save As dialog boxes with it, and its Load and Save methods also work with files and byte arrays directly. Starting from the form of your first application, the steps below add New, Open, Save and Save As, remember the current file, and ask before unsaved changes are lost.
Prerequisites
- The application from Create Your First Windows Forms Application, with a
TextControlnamedtextControl1onForm1. - Four
Buttoncontrols on the form, namednewButton,openButton,saveButtonandsaveAsButton. Double-click each one in the designer to create itsClickhandler. Menu items or ribbon buttons work the same way.
How Loading and Saving Works
Load replaces the complete contents of the editor with a document, and Save writes the complete document. Both come in two kinds of overloads:
- With a dialog box. Without a file name,
Loadopens the Open dialog box andSaveopens the Save As dialog box. TheStreamTypevalues you pass decide which file format filters the dialog offers, and the method returns theDialogResultof the dialog. - Without a dialog box. With a file path, a stream, a byte array or a string, the methods load and save directly.
Savecreates the file or overwrites it.
Supported File Formats lists the formats and their StreamType values.
Add New, Open, Save and Save As
Replace the contents of Form1.cs with the following code, and keep the namespace that Visual Studio created around the class:
using System;
using System.IO;
using System.Windows.Forms;
using TXTextControl;
public partial class Form1 : Form
{
// The formats offered in the Open and Save As dialog boxes
private const StreamType DocumentFormats =
StreamType.WordprocessingML | StreamType.RichTextFormat |
StreamType.HTMLFormat | StreamType.AdobePDF;
private string currentFile; // null until the document has a file
private StreamType currentStreamType;
private bool isModified;
public Form1()
{
InitializeComponent();
textControl1.Changed += textControl1_Changed;
FormClosing += Form1_FormClosing;
UpdateCaption();
}
private void newButton_Click(object sender, EventArgs e)
{
if (!ConfirmSaveChanges())
{
return;
}
textControl1.ResetContents();
currentFile = null;
isModified = false;
UpdateCaption();
}
private void openButton_Click(object sender, EventArgs e)
{
if (!ConfirmSaveChanges())
{
return;
}
LoadSettings loadSettings = new LoadSettings()
{
// Import the merge fields of Word documents as fields
ApplicationFieldFormat = ApplicationFieldFormat.MSWord
};
// Show the Open dialog box. Cancel leaves the document unchanged.
if (textControl1.Load(DocumentFormats | StreamType.AllFormats, loadSettings) != DialogResult.OK)
{
return;
}
currentFile = loadSettings.LoadedFile;
currentStreamType = loadSettings.LoadedStreamType;
isModified = false;
UpdateCaption();
}
private void saveButton_Click(object sender, EventArgs e)
{
SaveDocument();
}
private void saveAsButton_Click(object sender, EventArgs e)
{
SaveDocumentAs();
}
private bool SaveDocument()
{
// A new document has no file yet
if (currentFile == null)
{
return SaveDocumentAs();
}
textControl1.Save(currentFile, currentStreamType);
isModified = false;
UpdateCaption();
return true;
}
private bool SaveDocumentAs()
{
SaveSettings saveSettings = new SaveSettings();
// Show the Save As dialog box
if (textControl1.Save(DocumentFormats, saveSettings) != DialogResult.OK)
{
return false;
}
currentFile = saveSettings.SavedFile;
currentStreamType = saveSettings.SavedStreamType;
isModified = false;
UpdateCaption();
return true;
}
private void textControl1_Changed(object sender, EventArgs e)
{
if (!isModified)
{
isModified = true;
UpdateCaption();
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!ConfirmSaveChanges())
{
e.Cancel = true;
}
}
// Returns false if the user canceled
private bool ConfirmSaveChanges()
{
if (!isModified)
{
return true;
}
DialogResult result = MessageBox.Show(
"Do you want to save the changes to the document?",
"Save Changes",
MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question);
if (result == DialogResult.Cancel)
{
return false;
}
if (result == DialogResult.Yes)
{
return SaveDocument();
}
return true;
}
private void UpdateCaption()
{
string name = currentFile == null ? "Untitled" : Path.GetFileName(currentFile);
Text = name + (isModified ? "*" : "") + " - My Editor";
}
}
The code works as follows:
- New. ResetContents deletes the complete contents of the editor.
- Open.
LoadwithStreamTypevalues and a LoadSettings object shows the Open dialog box with the filters of these formats.StreamType.AllFormatsadds an All Formats item that shows every file the dialog can open. After the user has opened a file, LoadedFile and LoadedStreamType contain its path and format. - Word fields. ApplicationFieldFormat set to
MSWordimports the fields of Word and RTF documents, such as merge fields, into ApplicationFields. Without it, the fields are not imported as fields. - Save. A document that has a file is saved to it in its format. A new document goes to Save As.
- Save As.
SavewithStreamTypevalues and a SaveSettings object shows the Save As dialog box. SavedFile and SavedStreamType contain the path and format the user chose. - Unsaved changes. Changed occurs when the contents change. The code marks the document as modified, shows an asterisk in the caption, and asks before New, Open or closing the form discards the changes.
Press F5, type some text and click saveAsButton. Save the document as DOCX, change it, and click newButton: the application asks whether to save the changes.
Load and Save Without a Dialog Box
For files your code knows, pass the path and the format:
textControl1.Load("template.docx", StreamType.WordprocessingML);
textControl1.Save("letter.rtf", StreamType.RichTextFormat);
A document that comes from a database or a web service, or goes into an email attachment, is usually a byte array. Load and Save take it with a BinaryStreamType:
// Load a document from a byte array
byte[] data = File.ReadAllBytes("template.docx");
textControl1.Load(data, BinaryStreamType.WordprocessingML);
// Save the document to byte arrays, as DOCX and as PDF
byte[] docx;
textControl1.Save(out docx, BinaryStreamType.WordprocessingML);
byte[] pdf;
textControl1.Save(out pdf, BinaryStreamType.AdobePDF);
Save creates the arrays, so you do not allocate them.
Save Document Properties
SaveSettings also carries the properties of the document, such as its title and author, and TextControl.DocumentSettings contains the properties of a loaded document. Save the Document as PDF sets them in a first example, and Document Properties explains them in detail.
Add the Commands to the Ribbon
In a ribbon application, New, Open, Save and Save As belong in the Application Menu, the File tab. It has no commands of its own: select the ribbon, open the collection editor of ApplicationMenuItems in the Properties window and add a RibbonButton for each command. Their Click handlers call the same methods as the buttons above.
The TX Words sample installed with the setup implements these commands with a ribbon, in %USERPROFILE%\Documents\TX Text Control 34.0.NET for Windows Forms\CSharp\TX Words\Ribbon.
Next Steps
- Create a Document Programmatically: build a document in code.
- Create a PDF: PDF options such as passwords and PDF/A.
- Loading and Saving Documents: configure the Open and Save As dialog boxes and find the other load and save options.
- Supported File Formats: the formats you can load and save.