Migrating BrowserUI from Actipro WPF Controls Sample to standalone project

Docking/MDI for WPF Forum

Posted 11 months ago by Danielx64
Version: 23.1.0
Avatar

Hi there,

I'm currently taking the Docking/MDI for WPF control for a test run and I really liked the BrowserUI example. NowI was a little naughty and edited the sample code to replace the old IE engine with WebView2 and got it all working (code below for those interested in what I did).

Now I am trying to basicly pick up the code and port it over to the real project and I am running into some trouble. It seens that it is using some sort of "sampleBrowser:ProductItemControl" tag and I am having trouble working out what to do with it.

Is there any like decent guidence on what to do with tags such as sampleBrowser:ProductItemControl?

Cheers

MainControl.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using ActiproSoftware.Windows.Controls.Docking;
using System;
using Microsoft.Web.WebView2.Wpf;
using Microsoft.Web.WebView2.Core;
using System.IO;
using System.Collections.Generic;


namespace ActiproSoftware.ProductSamples.DockingSamples.QuickStart.BrowserUI {

	/// <summary>
	/// Provides the main user control for this sample.
	/// </summary>
	public partial class MainControl {

		private int browserIndex = 0;

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// OBJECT
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Initializes an instance of the <c>MainControl</c> class.
		/// </summary>
		public MainControl() {
			InitializeComponent();

			this.AddTab("http://www.bing.com");
		}
		public static class Globals
		{
			public static readonly String APP_FOLDER_NAME = "your app folder name"; // Unmodifiable
			public static readonly String URI_SCHEMA = "ms-mobile-apps:///providers/Microsoft.PowerApps/apps/";
			public static readonly String APP_REQUEST_LANG = "en-AU";
			public static readonly String USER_DATA_FOLDER = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), APP_FOLDER_NAME);
		}
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// NON-PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		private void AddTab(string url)
		{
			CreateBrowserWindow(new Uri(url));
		}
		/// <summary>
		/// Creates a new web browser <see cref="DocumentWindow"/>.
		/// </summary>
		/// <param name="url">The URL to load.</param>
		/// <returns>The <see cref="DocumentWindow"/> that was created.</returns>
		private DocumentWindow CreateBrowserWindow(Uri url) {
			var options = new CoreWebView2EnvironmentOptions
			{
				AllowSingleSignOnUsingOSPrimaryAccount = true,
				Language = $"{Globals.APP_REQUEST_LANG}"
			};
			var userDataFolder = System.IO.Path.Combine(Globals.USER_DATA_FOLDER);

			if (!Directory.Exists(Globals.USER_DATA_FOLDER))
			{
				Directory.CreateDirectory(Globals.USER_DATA_FOLDER);
			}
			var webView2Environment = CoreWebView2Environment.CreateAsync(null, userDataFolder, options).Result;

			//create new instance setting userDataFolder
			WebView2 browser = new WebView2();
			browser.EnsureCoreWebView2Async(webView2Environment);

			browser.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;


			
			InteropFocusTracking.SetIsEnabled(browser, true);

			// Create the document
			var documentWindow = new DocumentWindow(dockSite, "Browser" + (++browserIndex), "New Tab", null, browser);

			// Activate the document
			documentWindow.Activate();

			// Navigate to a page
			browser.Source = url;

			return documentWindow;
		}
		private void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
		{

			if (sender != null)
			{
				WebView2 wv = (WebView2)sender;
				wv.CoreWebView2.Settings.AreDefaultContextMenusEnabled = true;
				wv.CoreWebView2.Settings.AreDevToolsEnabled = false;
				wv.CoreWebView2.Settings.IsStatusBarEnabled = false;
				wv.CoreWebView2.Settings.AreBrowserAcceleratorKeysEnabled = false;
				wv.CoreWebView2.Settings.AreHostObjectsAllowed = false;
				wv.CoreWebView2.Settings.IsWebMessageEnabled = false;
				wv.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
				wv.CoreWebView2.Settings.IsGeneralAutofillEnabled = false;
				wv.CoreWebView2.Settings.IsPasswordAutosaveEnabled = false;
				wv.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
				wv.CoreWebView2.ContextMenuRequested += menurequested;
			}
		}
		/// <summary>
		/// Occurs when the browser completes page loading.
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The <c>NavigationEventArgs</c> that contained data related to this event.</param>
		private void OnBrowserLoadCompleted(object sender, NavigationEventArgs e) {
			var browser = (WebView2)sender;
			//this.UpdateUrlAndTitle(browser);
		}

		/// <summary>
		/// Occurs when the browser starts navigation.
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The <c>NavigationEventArgs</c> that contained data related to this event.</param>
		private void OnBrowserNavigated(object sender, NavigationEventArgs e) {
			var browser = (WebView2)sender;
			//this.UpdateUrlAndTitle(browser);
		}

		/// <summary>
		/// Occurs when a new window is requested by the user.
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The <c>RoutedEventArgs</c> that contained data related to this event.</param>
		private void OnDockSiteNewWindowRequested(object sender, RoutedEventArgs e) {
			this.AddTab("Https://google.com");
		}
		
		/// <summary>
		/// Occurs when a docking window is activated.
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The <c>DockingWindowEventArgs</c> that contains data related to this event.</param>
		private void OnDockSiteWindowActivated(object sender, DockingWindowEventArgs e) {
			var browser = (e.Window != null ? e.Window.Content as WebView2 : null);
			if (browser != null) ;
			//	this.UpdateUrlAndTitle(browser);
		}
		
		/// <summary>
		/// Occurs when a docking window is registered.
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The <c>DockingWindowEventArgs</c> that contains data related to this event.</param>
		private void OnDockSiteWindowRegistered(object sender, DockingWindowEventArgs e) {
			var browser = (WebView2)e.Window.Content;
			//browser.LoadCompleted += OnBrowserLoadCompleted;
			//browser.Navigated += OnBrowserNavigated;
		}

		/// <summary>
		/// Occurs when a docking window is registered.
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The <c>DockingWindowEventArgs</c> that contains data related to this event.</param>
		private void OnDockSiteWindowUnregistered(object sender, DockingWindowEventArgs e) {
			var browser = (WebView2)e.Window.Content;
		//	browser.LoadCompleted -= OnBrowserLoadCompleted;
		//	browser.Navigated -= OnBrowserNavigated;

			// Ensure there is always at least one browser tab
			if (dockSite.DocumentWindows.Count == 0)
				this.AddTab("about:blank");
		}
		


		/// <summary>
		/// Updates the URL and title from the specified web browser.
		/// </summary>
		/// <param name="browser">The <see cref="WebBrowser"/> to examine.</param>
		private void UpdateUrlAndTitle(WebBrowser browser) {
			try {
			//	urlTextBox.Text = (browser.Source != null ? browser.Source.ToString() : string.Empty);
			//	var window = (DocumentWindow)browser.Parent;
			//	window.Title = urlTextBox.Text;
			//	window.FileName = urlTextBox.Text;
			}
			catch {}
		}
		private void menurequested(object sender, CoreWebView2ContextMenuRequestedEventArgs args)
		{

			IList<CoreWebView2ContextMenuItem> menuList = args.MenuItems;
			CoreWebView2ContextMenuTargetKind context = args.ContextMenuTarget.Kind;
			if (context == CoreWebView2ContextMenuTargetKind.Audio)
			{
				for (int index = menuList.Count - 1; index >= 0; index--)
				{
					menuList.RemoveAt(index);
				}
			}
			if (context == CoreWebView2ContextMenuTargetKind.Image)
			{
				for (int index = menuList.Count - 1; index >= 0; index--)
				{
					menuList.RemoveAt(index);
				}
			}
			if (context == CoreWebView2ContextMenuTargetKind.Page)
			{
				for (int index = menuList.Count - 1; index >= 0; index--)
				{
					if (menuList[index].Name != "reload") { menuList.RemoveAt(index); }
				}
			}
			if (context == CoreWebView2ContextMenuTargetKind.SelectedText)
			{
				for (int index = menuList.Count - 1; index >= 0; index--)
				{
					if (menuList[index].Name != "copy" && menuList[index].Name != "paste" && menuList[index].Name != "cut") { menuList.RemoveAt(index); }
				}
			}
			if (context == CoreWebView2ContextMenuTargetKind.Video)
			{
				for (int index = menuList.Count - 1; index >= 0; index--)
				{
					menuList.RemoveAt(index);
				}
			}

		}

		private void CoreWebView2_NewWindowRequested(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
		{
			//WebView2 wv = (WebView2)_webView2Tabs[SelectedIndex].Content;
			if (e.Uri.Contains("apps.powerapps.com/play/e/"))
			{
				e.NewWindow = (CoreWebView2)sender;
				e.Handled = true;
			}
			else if (e.Uri.Contains("edge://gpu"))
			{
				e.NewWindow = (CoreWebView2)sender;
				e.Handled = true;
			}
			else
			{
				AddTab(e.Uri);
				e.Handled = true;
			}
		}
	}

}

MainControl.xaml

<sampleBrowser:ProductItemControl 
	x:Class="ActiproSoftware.ProductSamples.DockingSamples.QuickStart.BrowserUI.MainControl"
	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"
	xmlns:sampleBrowser="clr-namespace:ActiproSoftware.SampleBrowser"
	>

	<sampleBrowser:ProductItemControl.Resources>

		<Style x:Key="BrowserTabControlStyle" TargetType="docking:AdvancedTabControl">
			<Setter Property="TabBackground" Value="#e0e0e0" />
			<Setter Property="TabBackgroundActiveSelected" Value="#ffffff" />
			<Setter Property="TabBackgroundInactiveSelected" Value="#ffffff" />
			<Setter Property="TabBackgroundPointerOver" Value="#ebebeb" />
			<Setter Property="TabBackgroundPreview" Value="#e0e0e0" />
			<Setter Property="TabBackgroundPreviewActiveSelected" Value="#ffffff" />
			<Setter Property="TabBackgroundPreviewPointerOver" Value="#ebebeb" />
			<Setter Property="TabBorderBrush" Value="#9f9f9f" />
			<Setter Property="TabBorderBrushActiveSelected" Value="#9f9f9f" />
			<Setter Property="TabBorderBrushInactiveSelected" Value="#9f9f9f" />
			<Setter Property="TabBorderBrushPointerOver" Value="#ababab" />
			<Setter Property="TabBorderBrushPreview" Value="#9f9f9f" />
			<Setter Property="TabBorderBrushPreviewActiveSelected" Value="#9f9f9f" />
			<Setter Property="TabBorderBrushPreviewPointerOver" Value="#ababab" />
			<Setter Property="TabForeground" Value="#616161" />
			<Setter Property="TabForegroundActiveSelected" Value="#000000" />
			<Setter Property="TabForegroundInactiveSelected" Value="#000000" />
			<Setter Property="TabForegroundPointerOver" Value="#616161" />
			<Setter Property="TabForegroundPreview" Value="#000000" />
			<Setter Property="TabForegroundPreviewPointerOver" Value="#616161" />
			<Setter Property="TabForegroundPreviewActiveSelected" Value="#000000" />

			<Setter Property="AreTabEmbeddedButtonsAlwaysVisible" Value="True" />
			<Setter Property="Background" Value="#ffffff" />
			<Setter Property="BorderBrush" Value="#9f9f9f" />
			<Setter Property="BorderThickness" Value="1" />
			<Setter Property="CanTabsCloseOnMiddleClick" Value="True" />
			<Setter Property="CanTabsDrag" Value="True" />
			<Setter Property="HasNewTabButton" Value="True" />
			<Setter Property="HasTabCloseButtons" Value="True" />
			<Setter Property="HighlightThickness" Value="0" />
			<Setter Property="TabCornerRadius" Value="2" />
			<Setter Property="TabNearSlantExtent" Value="8" />
			<Setter Property="TabFarSlantExtent" Value="8" />
			<Setter Property="TabPadding" Value="5,4" />
			<Setter Property="TabSpacing" Value="-10" />

			<Setter Property="NewTabButtonStyle">
				<Setter.Value>
					<Style TargetType="docking:NewTabButton">
						<Setter Property="Background" Value="#e0e0e0" />
						<Setter Property="BorderBrush" Value="#9f9f9f" />
						<Setter Property="Margin" Value="6,4,0,0" />
						<Setter Property="Width" Value="32" />
						<Setter Property="Height" Value="16" />
						<Setter Property="VerticalAlignment" Value="Top" />
						<Setter Property="Template">
							<Setter.Value>
								<ControlTemplate TargetType="docking:NewTabButton">
									<Path Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}"
										  Data="M 0.5,1.5 Q 0.5,0.5 1.5,0.5 L 23.5,0.5 Q 27.5,0.5 31.5,14.5 Q 31.5,15.5 30.5,15.5 L 8.5,15.5 Q 4.5,15.5 0.5,1.5 Z" />

									<ControlTemplate.Triggers>
										<Trigger Property="IsMouseOver" Value="True">
											<Setter Property="Background" Value="#ebebeb" />
											<Setter Property="BorderBrush" Value="#ababab" />
										</Trigger>
									</ControlTemplate.Triggers>
								</ControlTemplate>
							</Setter.Value>
						</Setter>
					</Style>
				</Setter.Value>
			</Setter>
		</Style>

		<Style TargetType="docking:TabbedMdiContainer">
			<Setter Property="MinTabExtent" Value="200" />
			<Setter Property="MaxTabExtent" Value="200" />
		</Style>

	</sampleBrowser:ProductItemControl.Resources>

	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition Height="Auto" />
			<RowDefinition Height="*" />
		</Grid.RowDefinitions>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="*" />
			<ColumnDefinition Width="Auto" />
		</Grid.ColumnDefinitions>

		<!-- DockSite -->
		<docking:DockSite x:Name="dockSite" Grid.Row="1" Grid.ColumnSpan="2" 
						  AreNewTabsInsertedBeforeExistingTabs="False"
						  UseHostedPopups="False"
						  NewWindowRequested="OnDockSiteNewWindowRequested"
						  WindowActivated="OnDockSiteWindowActivated"
						  WindowRegistered="OnDockSiteWindowRegistered"
						  WindowUnregistered="OnDockSiteWindowUnregistered"
						  >
			<docking:DockSite.Switcher>
				<docking:StandardSwitcher AreToolWindowsVisible="False" />
			</docking:DockSite.Switcher>

			<!-- Workspace -->
			<docking:Workspace>
				<docking:TabbedMdiHost x:Name="tabbedMdiHost" TabControlStyle="{StaticResource BrowserTabControlStyle}" ContainersHaveNewTabButtons="True" TabOverflowBehavior="Shrink" />
            </docking:Workspace>

		</docking:DockSite>

	</Grid>

</sampleBrowser:ProductItemControl>

Comments (1)

Posted 11 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

ProductItemControl is effectively just a plain old UserControl but with a couple extra features for sample display in our samples app.  You can copy it's contents to any UserControl or Window in your app.


Actipro Software Support

The latest build of this product (v24.1.2) was released 8 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.