diff --git a/CefSharp.Wpf.Example/App.xaml b/CefSharp.Wpf.Example/App.xaml index 38d64b8ff5..184cec1910 100644 --- a/CefSharp.Wpf.Example/App.xaml +++ b/CefSharp.Wpf.Example/App.xaml @@ -1,4 +1,87 @@  + xmlns:controls="clr-namespace:CefSharp.Wpf.Example.Controls" + xmlns:views="clr-namespace:CefSharp.Wpf.Example.Views.Main" + xmlns:browserTab="clr-namespace:CefSharp.Wpf.Example.Views.BrowserTab" + StartupUri="MainWindow.xaml"> + + + + + + + + + + + diff --git a/CefSharp.Wpf.Example/App.xaml.cs b/CefSharp.Wpf.Example/App.xaml.cs index a44df3d687..6d17f67936 100644 --- a/CefSharp.Wpf.Example/App.xaml.cs +++ b/CefSharp.Wpf.Example/App.xaml.cs @@ -1,4 +1,8 @@ -using System.Windows; +// Copyright © 2010-2014 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +using System.Windows; using CefSharp.Example; namespace CefSharp.Wpf.Example diff --git a/CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj b/CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj index 63fe18a9a8..5f7d61519c 100644 --- a/CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj +++ b/CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj @@ -96,13 +96,14 @@ MSBuild:Compile Designer + - - MainView.xaml + + BrowserTabView.xaml - + MSBuild:Compile Designer @@ -117,9 +118,9 @@ MainWindow.xaml Code - - Designer + MSBuild:Compile + Designer diff --git a/CefSharp.Wpf.Example/Controls/TabControlEx.cs b/CefSharp.Wpf.Example/Controls/TabControlEx.cs new file mode 100644 index 0000000000..51703bd9c0 --- /dev/null +++ b/CefSharp.Wpf.Example/Controls/TabControlEx.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Specialized; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; + +namespace CefSharp.Wpf.Example.Controls +{ + /// + /// NOTE: Source directly imported from http://stackoverflow.com/a/9802346 + /// TabControlEx - Extended TabControl which saves the displayed item so you don't get the performance hit of + /// unloading and reloading the VisualTree when switching tabs + /// Obtained from http://www.pluralsight-training.net/community/blogs/eburke/archive/2009/04/30/keeping-the-wpf-tab-control-from-destroying-its-children.aspx + /// and made a some modifications so it reuses a TabItem's ContentPresenter when doing drag/drop operations + /// + [TemplatePart(Name = "PART_ItemsHolder", Type = typeof(Panel))] + public class TabControlEx : TabControl + { + private Panel itemsHolderPanel; + + public TabControlEx() + { + // This is necessary so that we get the initial databound selected item + ItemContainerGenerator.StatusChanged += ItemContainerGeneratorStatusChanged; + } + + /// + /// If containers are done, generate the selected item + /// + /// + /// + private void ItemContainerGeneratorStatusChanged(object sender, EventArgs e) + { + if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) + { + ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged; + UpdateSelectedItem(); + } + } + + /// + /// Get the ItemsHolder and generate any children + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + itemsHolderPanel = GetTemplateChild("PART_ItemsHolder") as Panel; + UpdateSelectedItem(); + } + + /// + /// 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) + { + var 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 + var 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; + + var 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() + { + var selectedItem = SelectedItem; + if (selectedItem == null) + return null; + + var item = selectedItem as TabItem ?? ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as TabItem; + + return item; + } + } +} diff --git a/CefSharp.Wpf.Example/MainWindow.xaml b/CefSharp.Wpf.Example/MainWindow.xaml index 296f017d95..e06c55168b 100644 --- a/CefSharp.Wpf.Example/MainWindow.xaml +++ b/CefSharp.Wpf.Example/MainWindow.xaml @@ -1,27 +1,41 @@  - - - - - - - - - - - - + + + + + + + + + + +