Skip to content

Commit

Permalink
Merge pull request #143 from matko238/master
Browse files Browse the repository at this point in the history
Replaced TabControl with TabControlEx
  • Loading branch information
Dirkster99 authored Apr 12, 2020
2 parents 5ce9591 + b69086d commit 74641ff
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ namespace AvalonDock.Controls
/// Provides a control to display multible (or just one) LayoutAnchorable(s).
/// See also <seealso cref="AnchorablePaneTabPanel"/>.
/// </summary>
/// <seealso cref="TabControl"/>
/// <seealso cref="TabControlEx"/>
/// <seealso cref="ILayoutControl"/>
public class LayoutAnchorablePaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer
public class LayoutAnchorablePaneControl : TabControlEx, ILayoutControl//, ILogicalChildrenContainer
{
#region fields
private LayoutAnchorablePane _model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ namespace AvalonDock.Controls
/// TabItem Header (<see cref="LayoutDocumentTabItem"/>) that contains the document titles
/// inside the <see cref="DocumentPaneTabPanel"/>.
/// </summary>
/// <seealso cref="TabControl"/>
/// <seealso cref="TabControlEx"/>
/// <seealso cref="ILayoutControl"/>
public class LayoutDocumentPaneControl : TabControl, ILayoutControl//, ILogicalChildrenContainer
public class LayoutDocumentPaneControl : TabControlEx, ILayoutControl//, ILogicalChildrenContainer
{
#region fields
private LayoutDocumentPane _model;
Expand Down
201 changes: 201 additions & 0 deletions source/Components/AvalonDock/TabControlEx.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// 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
/// </summary>
[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;
}

/// <summary>
/// If containers are done, generate the selected item
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
this.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
UpdateSelectedItem();
}
}

/// <summary>
/// Get the ItemsHolder and generate any children
/// </summary>
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;
}

/// <summary>
/// When the items change we remove any generated panel children and add any new ones as necessary
/// </summary>
/// <param name="e"></param>
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;
}
}
}

0 comments on commit 74641ff

Please # to comment.