Here is a sample application that shows the concept. Just create a new project in Visual Studio and paste in the following XAML and cs code. Both the Add button at the bottom and the + button at the top will add a new document.
Here is the XAML first.
<Window x:Class="ActiProAddTab.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:docking="http://schemas.actiprosoftware.com/winfx/xaml/docking"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel x:Name="mainDockPanel" LastChildFill="True" Grid.Row="0" Margin="0" >
<docking:DockSite x:Name="dockSite" >
<docking:Workspace >
<docking:TabbedMdiHost x:Name="tabbedMdiHost" Background="LightGray" IsCloseButtonOnTab="False">
<docking:TabbedMdiContainer x:Name="documentContainer" >
</docking:TabbedMdiContainer>
</docking:TabbedMdiHost>
</docking:Workspace>
</docking:DockSite>
</DockPanel>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button x:Name="btnAdd" Content="Add..." PreviewMouseDown="btnAdd_MouseDown" />
</StackPanel>
</Grid>
</Window>
And now the code behind.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
TextBlock text = new TextBlock();
text.Text = "Hello, this is document number " + dockSite.DocumentWindows.Count.ToString();
AddDocWindow(text, dockSite, "Document" + dockSite.DocumentWindows.Count.ToString());
AddPlusButton();
}
public Grid CreateHeaderGrid(string strName, string strToolTip = "")
{
// Create the header
Grid headerGrid = new Grid();
headerGrid.ColumnDefinitions.Add(new ColumnDefinition());
TextBlock titleText = new TextBlock();
titleText.Text = strName;
headerGrid.Children.Add(titleText);
titleText.SetValue(Grid.ColumnProperty, 0);
if (strToolTip != "")
{
TextBlock txtToolTip = new TextBlock();
txtToolTip.Text = strToolTip;
headerGrid.ToolTip = txtToolTip;
}
return (headerGrid);
}
private DocumentWindow AddWindow(string name, DockSite dockSite, Grid headerGrid)
{
var newDocWindow = new DocumentWindow(dockSite, null, name, null, null);
newDocWindow.Header = headerGrid;
newDocWindow.CanRaft = true;
newDocWindow.CanClose = false;
newDocWindow.Name = name.Replace(" ", "");
newDocWindow.Activate();
return newDocWindow;
}
public void AddDocWindow(Object control, DockSite dockSite, string name)
{
Grid newHeaderGrid = CreateHeaderGrid(name, "My happy tooltip");
DocumentWindow docWin = AddWindow(name, dockSite, newHeaderGrid);
docWin.Content = control;
}
private void btnAdd_MouseDown(object sender, MouseButtonEventArgs e)
{
TextBlock text = new TextBlock();
text.Text = "Hello, this is document number " + dockSite.DocumentWindows.Count.ToString();
AddDocWindow(text, dockSite, "Document" + dockSite.DocumentWindows.Count.ToString());
}
private void AddPlusButton()
{
var panels = FindVisualChildren<ReverseMeasureDockPanel>(documentContainer);
ReverseMeasureDockPanel panel = panels.Where(r => r is FrameworkElement).First(r => (r.Parent as FrameworkElement).Name == "tabContainer");
Button addButton = new Button();
addButton.PreviewMouseDown += new MouseButtonEventHandler(addButton_PreviewMouseDown);
addButton.Content = "+";
panel.Children.Add(addButton);
ReverseMeasureDockPanel.SetDock(addButton, Dock.Left);
}
private void addButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
TextBlock text = new TextBlock();
text.Text = "Hello, this is document number " + dockSite.DocumentWindows.Count.ToString();
AddDocWindow(text, dockSite, "Document" + dockSite.DocumentWindows.Count.ToString());
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
}