diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs
index d1a37a02..8c426ba1 100644
--- a/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs
+++ b/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs
@@ -21,9 +21,9 @@ namespace AvalonDock.Controls
/// Provides a control to display multible (or just one) LayoutAnchorable(s).
/// See also .
///
- ///
+ ///
///
- public class LayoutAnchorablePaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer
+ public class LayoutAnchorablePaneControl : TabControlEx, ILayoutControl//, ILogicalChildrenContainer
{
#region fields
private LayoutAnchorablePane _model;
diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs
index 517fb2e2..dbd3e132 100644
--- a/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs
+++ b/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs
@@ -22,9 +22,9 @@ namespace AvalonDock.Controls
/// TabItem Header () that contains the document titles
/// inside the .
///
- ///
+ ///
///
- public class LayoutDocumentPaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer
+ public class LayoutDocumentPaneControl : TabControlEx, ILayoutControl//, ILogicalChildrenContainer
{
#region fields
private LayoutDocumentPane _model;
diff --git a/source/Components/AvalonDock/TabControlEx.cs b/source/Components/AvalonDock/TabControlEx.cs
new file mode 100644
index 00000000..721939b5
--- /dev/null
+++ b/source/Components/AvalonDock/TabControlEx.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections.Specialized;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+
+namespace AvalonDock
+{
+ ///
+ /// This control added to mitigate issue with tab (document) switching speed
+ /// See this https://stackoverflow.com/questions/2080764/how-to-preserve-control-state-within-tab-items-in-a-tabcontrol
+ /// and this https://stackoverflow.com/questions/31030293/cefsharp-in-tabcontrol-not-working/37171847#37171847
+ ///
+ [TemplatePart(Name = "PART_ItemsHolder", Type = typeof(Panel))]
+ public class TabControlEx : TabControl
+ {
+ private Panel ItemsHolderPanel = null;
+
+ public TabControlEx()
+ : base()
+ {
+ // This is necessary so that we get the initial databound selected item
+ ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
+ }
+
+ ///
+ /// If containers are done, generate the selected item
+ ///
+ ///
+ ///
+ private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
+ {
+ if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
+ {
+ this.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
+ UpdateSelectedItem();
+ }
+ }
+
+ ///
+ /// Get the ItemsHolder and generate any children
+ ///
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ ItemsHolderPanel = CreateGrid();
+ // exchange ContentPresenter for Grid
+ var topGrid = (Grid)GetVisualChild(0);
+
+ if (topGrid != null)
+ {
+ if (topGrid.Children != null && topGrid.Children.Count > 2)
+ {
+ if (topGrid.Children[1] is Border)
+ {
+ var border = (Border)topGrid.Children[1];
+ border.Child = ItemsHolderPanel;
+ }
+ else if (topGrid.Children[2] is Border)
+ {
+ var border = (Border)topGrid.Children[2];
+ border.Child = ItemsHolderPanel;
+ }
+ }
+ }
+
+ UpdateSelectedItem();
+ }
+
+ private Grid CreateGrid()
+ {
+ var grid = new Grid();
+ Binding binding = new Binding(PaddingProperty.Name);
+ binding.Source = this; // view model?
+ grid.SetBinding(Grid.MarginProperty, binding);
+
+ binding = new Binding(SnapsToDevicePixelsProperty.Name);
+ binding.Source = this; // view model?
+ grid.SetBinding(Grid.SnapsToDevicePixelsProperty, binding);
+
+ return grid;
+ }
+
+ ///
+ /// When the items change we remove any generated panel children and add any new ones as necessary
+ ///
+ ///
+ protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
+ {
+ base.OnItemsChanged(e);
+
+ if (ItemsHolderPanel == null)
+ return;
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Reset:
+ ItemsHolderPanel.Children.Clear();
+ break;
+
+ case NotifyCollectionChangedAction.Add:
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldItems != null)
+ {
+ foreach (var item in e.OldItems)
+ {
+ ContentPresenter cp = FindChildContentPresenter(item);
+ if (cp != null)
+ ItemsHolderPanel.Children.Remove(cp);
+ }
+ }
+
+ // Don't do anything with new items because we don't want to
+ // create visuals that aren't being shown
+
+ UpdateSelectedItem();
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ throw new NotImplementedException("Replace not implemented yet");
+ }
+ }
+
+ protected override void OnSelectionChanged(SelectionChangedEventArgs e)
+ {
+ base.OnSelectionChanged(e);
+ UpdateSelectedItem();
+ }
+
+ private void UpdateSelectedItem()
+ {
+ if (ItemsHolderPanel == null)
+ return;
+
+ // Generate a ContentPresenter if necessary
+ TabItem item = GetSelectedTabItem();
+ if (item != null)
+ CreateChildContentPresenter(item);
+
+ // show the right child
+ foreach (ContentPresenter child in ItemsHolderPanel.Children)
+ child.Visibility = ((child.Tag as TabItem).IsSelected) ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ private ContentPresenter CreateChildContentPresenter(object item)
+ {
+ if (item == null)
+ return null;
+
+ ContentPresenter cp = FindChildContentPresenter(item);
+
+ if (cp != null)
+ return cp;
+
+ // the actual child to be added. cp.Tag is a reference to the TabItem
+ cp = new ContentPresenter();
+ cp.Content = (item is TabItem) ? (item as TabItem).Content : item;
+ cp.ContentTemplate = this.SelectedContentTemplate;
+ cp.ContentTemplateSelector = this.SelectedContentTemplateSelector;
+ cp.ContentStringFormat = this.SelectedContentStringFormat;
+ cp.Visibility = Visibility.Collapsed;
+ cp.Tag = (item is TabItem) ? item : (this.ItemContainerGenerator.ContainerFromItem(item));
+ ItemsHolderPanel.Children.Add(cp);
+ return cp;
+ }
+
+ private ContentPresenter FindChildContentPresenter(object data)
+ {
+ if (data is TabItem)
+ data = (data as TabItem).Content;
+
+ if (data == null)
+ return null;
+
+ if (ItemsHolderPanel == null)
+ return null;
+
+ foreach (ContentPresenter cp in ItemsHolderPanel.Children)
+ {
+ if (cp.Content == data)
+ return cp;
+ }
+
+ return null;
+ }
+
+ protected TabItem GetSelectedTabItem()
+ {
+ object selectedItem = base.SelectedItem;
+ if (selectedItem == null)
+ return null;
+
+ TabItem item = selectedItem as TabItem;
+ if (item == null)
+ item = base.ItemContainerGenerator.ContainerFromIndex(base.SelectedIndex) as TabItem;
+
+ return item;
+ }
+ }
+}