Embedding the Editor in Windows and UserControls
Real applications place the editor inside larger user interfaces: a reusable user control that bundles the editor with its bars, a window that shows a letter next to its cover note, or a document window opened for each file. The WPF TextControl fits into any of them like other WPF controls. Three things need attention: the license when the editor lives in a control library, the names by which the editor finds its bars, and the moment each editor is ready.
The samples use a WPF project with the package TXTextControl.TextControl.WPF.SDK and the XAML prefix WPF for the controls of TX Text Control, as in XAML Integration.
Choose a Container
| Container | Use it when | What to take care of |
|---|---|---|
A Window | One editor fills a window | The layout; see WPF Layout and Resizing |
A RibbonWindow | The window has a ribbon with a Quick Access Toolbar in its title bar | See Create a WPF Ribbon Application |
A UserControl | The same editor, with its bars and methods, appears in several windows | The license, when the user control is in a control library; the names of the bars stay inside the user control |
| Several editors in one window | Documents are shown side by side | One set of bars that follows the editor with the focus, or one set per editor |
Put the Editor Into a UserControl
A user control bundles the editor, its bars and the methods the window needs. The following EditorControl.xaml holds an editor with a button bar and a status bar:
<UserControl x:Class="MyWPFApp.EditorControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPF="clr-namespace:TXTextControl.WPF;assembly=TXTextControl.WPF">
<DockPanel>
<WPF:ButtonBar x:Name="buttonBar1" DockPanel.Dock="Top" />
<WPF:StatusBar x:Name="statusBar1" DockPanel.Dock="Bottom" />
<WPF:TextControl x:Name="textControl1"
ButtonBar="buttonBar1" StatusBar="statusBar1"
Loaded="textControl1_Loaded" />
</DockPanel>
</UserControl>
The code-behind, EditorControl.xaml.cs, gives the window methods to load and save the document. A document that arrives before the editor is loaded waits until it is:
using System.Windows;
using System.Windows.Controls;
using TXTextControl;
namespace MyWPFApp
{
public partial class EditorControl : UserControl
{
private byte[] pendingDocument;
public EditorControl()
{
InitializeComponent();
}
// Give the host access to the editor
public TXTextControl.WPF.TextControl Editor => textControl1;
// Load a document now, or as soon as the editor is ready
public void LoadDocument(byte[] data)
{
if (textControl1.IsLoaded)
{
textControl1.Load(data, BinaryStreamType.InternalUnicodeFormat);
}
else
{
pendingDocument = data;
}
}
public byte[] SaveDocument()
{
textControl1.Save(out byte[] data, BinaryStreamType.InternalUnicodeFormat);
return data;
}
private void textControl1_Loaded(object sender, RoutedEventArgs e)
{
if (pendingDocument != null)
{
textControl1.Load(pendingDocument, BinaryStreamType.InternalUnicodeFormat);
pendingDocument = null;
}
}
}
}
The code works as follows:
- The names
buttonBar1andstatusBar1are defined in the XAML of the user control, and theTextControlin the same XAML finds them. Every instance of the user control has its own editor and its own bars. IsLoadedistrueonce WPF has loaded the editor into the window. A window typically callsLoadDocumentin its constructor, before that, so the document is kept and loaded in theLoadedhandler. Control Initialization and Document Access explains why.- Load and Save exchange the document as a byte array in
BinaryStreamType.InternalUnicodeFormat, the internal format of TX Text Control, which suits a database field. Editorgives the window direct access to theTextControl. Leave it out if the window should use only the methods of the user control.
A window declares the user control with a prefix for your own namespace and places it like any other control:
<Window x:Class="MyWPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWPFApp"
Title="MainWindow" Height="600" Width="1200">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<local:EditorControl x:Name="letterEditor" Grid.Column="0" />
<local:EditorControl x:Name="coverNoteEditor" Grid.Column="1" />
</Grid>
</Window>
In the constructor of the window, after InitializeComponent, a call such as letterEditor.LoadDocument(File.ReadAllBytes("letter.tx")) gives the left editor its document.
A UserControl in a Control Library
When the user control is in a separate control library, the license of TX Text Control is compiled into that library, not into the executable. Set TextControl.EntryAssembly to the library in the constructor of the user control, before InitializeComponent creates the TextControl:
// The license is compiled into this control library
TXTextControl.WPF.TextControl.EntryAssembly = typeof(EditorControl).Assembly;
InitializeComponent();
This works since version 32.0 with Service Pack 2. Application Licensing shows the complete control library. A user control in the application's own project doesn't need the line.
Editors in Tabs and Other Windows
- In a
TabControl, WPF shows only the content of the selected tab and loads it into the window when the tab is selected. TheLoadedevent of an editor can therefore occur more than once; code in its handler that must run only once, such as loading the first document, keeps a flag, as Control Initialization and Document Access shows. - In a second window, an editor is independent of the one in the main window, with its own document and its own bars declared in the XAML of that window.
Next Steps
- Creating and Configuring Controls in Code: create editors and bars at run time.
- Control Initialization and Document Access: when an editor is ready for its document.
- MVVM Integration Patterns: connect the editors of a window to view models.
- Application Licensing: the license in executables and control libraries.