diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs
index 8c426ba1..5f44d6ed 100644
--- a/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs
+++ b/source/Components/AvalonDock/Controls/LayoutAnchorablePaneControl.cs
@@ -30,13 +30,17 @@ public class LayoutAnchorablePaneControl : TabControlEx, ILayoutControl//, ILogi
#endregion fields
#region Constructors
-
+ /// Static class constructor to register WPF style keys.
static LayoutAnchorablePaneControl()
{
FocusableProperty.OverrideMetadata(typeof(LayoutAnchorablePaneControl), new FrameworkPropertyMetadata(false));
}
- public LayoutAnchorablePaneControl(LayoutAnchorablePane model)
+ /// Class constructor from model and virtualization parameter.
+ ///
+ /// Whether tabbed items are virtualized or not.
+ internal LayoutAnchorablePaneControl(LayoutAnchorablePane model, bool IsVirtualizing)
+ : base(IsVirtualizing)
{
_model = model ?? throw new ArgumentNullException(nameof(model));
SetBinding(ItemsSourceProperty, new Binding("Model.Children") { Source = this });
@@ -49,25 +53,44 @@ public LayoutAnchorablePaneControl(LayoutAnchorablePane model)
#endregion Constructors
#region Properties
-
+ /// Gets the layout model of this control.
public ILayoutElement Model => _model;
#endregion Properties
#region Overrides
-
+ ///
+ /// Invoked when an unhandled attached
+ /// event reaches an element in its route that is derived from this class.
+ /// Implement this method to add class handling for this event.
+ ///
+ /// The that contains the event data.
protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
if (_model?.SelectedContent != null) _model.SelectedContent.IsActive = true;
base.OnGotKeyboardFocus(e);
}
+ ///
+ /// Invoked when an unhandled routed
+ /// event is raised on this element. Implement this method to add class handling
+ /// for this event.
+ ///
+ /// The that contains the event data.
+ /// The event data reports that the left mouse button was pressed.
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (!e.Handled && _model?.SelectedContent != null) _model.SelectedContent.IsActive = true;
}
+ ///
+ /// Invoked when an unhandled routed
+ /// event reaches an element in its route that is derived from this class. Implement
+ /// this method to add class handling for this event.
+ ///
+ /// The that contains the event data. The
+ /// event data reports that the right mouse button was pressed.
protected override void OnMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseRightButtonDown(e);
diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs
index dbd3e132..31e18401 100644
--- a/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs
+++ b/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs
@@ -37,9 +37,11 @@ static LayoutDocumentPaneControl()
FocusableProperty.OverrideMetadata(typeof(LayoutDocumentPaneControl), new FrameworkPropertyMetadata(false));
}
- /// Class constructor from model parameter.
+ /// Class constructor from model and virtualization parameter.
///
- internal LayoutDocumentPaneControl(LayoutDocumentPane model)
+ /// Whether tabbed items are virtualized or not.
+ internal LayoutDocumentPaneControl(LayoutDocumentPane model, bool isVirtualizing)
+ : base(isVirtualizing)
{
_model = model ?? throw new ArgumentNullException(nameof(model));
SetBinding(ItemsSourceProperty, new Binding("Model.Children") { Source = this });
@@ -51,13 +53,19 @@ internal LayoutDocumentPaneControl(LayoutDocumentPane model)
#endregion Constructors
#region Properties
-
+ /// Gets the layout model of this control.
public ILayoutElement Model => _model;
#endregion Properties
#region Overrides
-
+ ///
+ /// Invoked when an unhandled routed
+ /// event is raised on this element. Implement this method to add class handling
+ /// for this event.
+ ///
+ /// The that contains the event data.
+ /// The event data reports that the left mouse button was pressed.
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
@@ -65,6 +73,13 @@ protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEv
_model.SelectedContent.IsActive = true;
}
+ ///
+ /// Invoked when an unhandled routed
+ /// event reaches an element in its route that is derived from this class. Implement
+ /// this method to add class handling for this event.
+ ///
+ /// The that contains the event data. The
+ /// event data reports that the right mouse button was pressed.
protected override void OnMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseRightButtonDown(e);
diff --git a/source/Components/AvalonDock/TabControlEx.cs b/source/Components/AvalonDock/Controls/TabControlEx.cs
similarity index 79%
rename from source/Components/AvalonDock/TabControlEx.cs
rename to source/Components/AvalonDock/Controls/TabControlEx.cs
index 721939b5..5d2993bb 100644
--- a/source/Components/AvalonDock/TabControlEx.cs
+++ b/source/Components/AvalonDock/Controls/TabControlEx.cs
@@ -5,45 +5,57 @@
using System.Windows.Controls.Primitives;
using System.Windows.Data;
-namespace AvalonDock
+namespace AvalonDock.Controls
{
///
/// 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
+ ///
+ /// by implmenting an option to enable virtualization for tabbed document containers.
///
[TemplatePart(Name = "PART_ItemsHolder", Type = typeof(Panel))]
public class TabControlEx : TabControl
{
+ #region fields
private Panel ItemsHolderPanel = null;
+ private readonly bool _IsVirtualizing;
+ #endregion fields
- public TabControlEx()
- : base()
+ #region constructors
+ ///
+ /// Class constructor from virtualization parameter.
+ ///
+ /// Whether tabbed items are virtualized or not.
+ public TabControlEx(bool isVirtualizing)
+ : this()
{
- // This is necessary so that we get the initial databound selected item
- ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
+ _IsVirtualizing = isVirtualizing;
}
///
- /// If containers are done, generate the selected item
+ /// Class constructor
///
- ///
- ///
- private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
+ protected TabControlEx()
+ : base()
{
- if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
- {
- this.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
- UpdateSelectedItem();
- }
+ // This is necessary so that we get the initial databound selected item
+ ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
+ #endregion constructors
+ #region methods
///
/// Get the ItemsHolder and generate any children
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
+
+ // Code below is required only if virtualization is turned ON
+ if (_IsVirtualizing == false)
+ return;
+
ItemsHolderPanel = CreateGrid();
// exchange ContentPresenter for Grid
var topGrid = (Grid)GetVisualChild(0);
@@ -68,19 +80,6 @@ public override void OnApplyTemplate()
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
@@ -90,6 +89,10 @@ protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
+ // Code below is required only if virtualization is turned ON
+ if (_IsVirtualizing == false)
+ return;
+
if (ItemsHolderPanel == null)
return;
@@ -122,12 +125,71 @@ protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
}
}
+ ///
+ /// Raises the routed event.
+ ///
+ /// Provides data for .
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
+
+ // Code below is required only if virtualization is turned ON
+ if (_IsVirtualizing == false)
+ return;
+
UpdateSelectedItem();
}
+ ///
+ /// Gets the currently selected item (including its generation if Virtualization is currently switched on).
+ ///
+ ///
+ protected TabItem GetSelectedTabItem()
+ {
+ object selectedItem = base.SelectedItem;
+
+ // Code below is required only if virtualization is turned ON
+ if (_IsVirtualizing == false)
+ return selectedItem as TabItem;
+
+ if (selectedItem == null)
+ return null;
+
+ TabItem item = selectedItem as TabItem;
+ if (item == null)
+ item = base.ItemContainerGenerator.ContainerFromIndex(base.SelectedIndex) as TabItem;
+
+ return item;
+ }
+
+ ///
+ /// 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();
+ }
+ }
+
+ 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;
+ }
+
private void UpdateSelectedItem()
{
if (ItemsHolderPanel == null)
@@ -184,18 +246,6 @@ private ContentPresenter FindChildContentPresenter(object data)
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;
- }
+ #endregion methods
}
}
diff --git a/source/Components/AvalonDock/DockingManager.cs b/source/Components/AvalonDock/DockingManager.cs
index 28ffb076..5382fc4e 100644
--- a/source/Components/AvalonDock/DockingManager.cs
+++ b/source/Components/AvalonDock/DockingManager.cs
@@ -1319,6 +1319,22 @@ public bool AllowMixedOrientation
#endregion AllowMixedOrientation
+ #region IsVirtualizingLayoutDocument IsVirtualizingLayoutAnchorable
+
+ ///
+ /// Gets/sets (a simple non-dependency property) to determine whether the
+ /// is virtualizing its tabbed item child controls or not.
+ ///
+ public bool IsVirtualizingLayoutDocument { get; set; }
+
+ ///
+ /// Gets/sets (a simple non-dependency property) to determine whether the
+ /// is virtualizing its tabbed item child controls or not.
+ ///
+ public bool IsVirtualizingLayoutAnchorable { get; set; }
+
+ #endregion IsVirtualizingLayoutDocument IsVirtualizingLayoutAnchorable
+
#endregion Public Properties
#region Private Properties
@@ -1506,13 +1522,13 @@ internal UIElement CreateUIElementForModel(ILayoutElement model)
if (model is LayoutDocumentPane)
{
- var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane);
+ var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane, IsVirtualizingLayoutDocument);
templateModelView.SetBinding(StyleProperty, new Binding(DocumentPaneControlStyleProperty.Name) { Source = this });
return templateModelView;
}
if (model is LayoutAnchorablePane)
{
- var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane);
+ var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane, IsVirtualizingLayoutAnchorable);
templateModelView.SetBinding(StyleProperty, new Binding(AnchorablePaneControlStyleProperty.Name) { Source = this });
return templateModelView;
}
diff --git a/source/TestApp/MainWindow.xaml b/source/TestApp/MainWindow.xaml
index 425d2e69..ba2a23d6 100644
--- a/source/TestApp/MainWindow.xaml
+++ b/source/TestApp/MainWindow.xaml
@@ -64,7 +64,9 @@
x:Name="dockManager"
Grid.Row="1"
AllowMixedOrientation="True"
- DocumentClosing="dockManager_DocumentClosing">
+ DocumentClosing="dockManager_DocumentClosing"
+ IsVirtualizingLayoutAnchorable="False"
+ IsVirtualizingLayoutDocument="False">