Hi fmartinez, thanks for your reply.
In order to "improve" prism interop when a WPF application/form is called inside Windows.Forms or VB6, our company did the following modifications that we want to share in case it is found useful for future release, individual or if someone sees a big potential problem with the change.
In order to "improve" prism interop when a WPF application/form is called inside Windows.Forms or VB6, our company did the following modifications that we want to share in case it is found useful for future release, individual or if someone sees a big potential problem with the change.
Change no. 1 - Added an "InteropHelper.cs" class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.Practices.Prism
{
/// <summary>
/// This class contains some usefull methods/properties used to interact with windows.forms applications
/// </summary>
public static class InteropHelper
{
/// <summary>
/// Returns if the current application is a windows.forms application.
/// </summary>
/// <returns>Returns if the current application is a windows.forms application.</returns>
public static bool IsWindowsFormsApplication()
{
return System.Windows.Application.Current == null
&& !string.IsNullOrWhiteSpace(System.Windows.Forms.Application.ExecutablePath)
&& System.Windows.Forms.Application.OpenForms.Count > 0;
}
private static object _fallBackDispatcherObject;
/// <summary>
/// Use to set the dispatcher to be used by prism if no WPF application is running.
/// </summary>
/// <remarks>
/// Can be set to one of the following type:
/// -System.Windows.Window
/// -System.Windows.Controls.UserControl
/// -System.Windows.Threading.Dispatcher
/// -System.Windows.Forms.Form
/// -System.Windows.Forms.Control
/// </remarks>
public static object FallBackDispatcherObject
{
get {
return _fallBackDispatcherObject;
}
set {
if (value is System.Windows.Window)
{
_fallBackDispatcherObject = ((System.Windows.Window)value).Dispatcher;
}
else if (value is System.Windows.Controls.UserControl)
{
_fallBackDispatcherObject = ((System.Windows.Controls.UserControl)value).Dispatcher;
}
else if (value is System.Windows.Threading.Dispatcher)
{
_fallBackDispatcherObject = value;
}
else if (value is System.Windows.Forms.Form)
{
_fallBackDispatcherObject = ((System.Windows.Forms.Form)value);
}
else if (value is System.Windows.Forms.Control)
{
_fallBackDispatcherObject = ((System.Windows.Forms.Control)value);
}
else
{
_fallBackDispatcherObject = null;
}
}
}
}
}
Change no. 2 - Modified RegionManager.cs IsInDesignMode property as follow:
private static bool IsInDesignMode(DependencyObject element)
{
//Note: this was modified in order to allow the regions to be loaded when prism
//is instantiated inside a windows.Form application
if (Application.Current != null)
{
// Due to a known issue in Cider, GetIsInDesignMode attached property value is not enough to know if it's in design mode.
return DesignerProperties.GetIsInDesignMode(element) || Application.Current.GetType() == typeof(Application);
}
else if (InteropHelper.IsWindowsFormsApplication())
{
return false;
}
else
return DesignerProperties.GetIsInDesignMode(element);
//else if (WindowsFormHelper.FallBackDispatcherObject !=null)
//{
// return false;
//}
//else
//{
// // Due to a known issue in Cider, GetIsInDesignMode attached property value is not enough to know if it's in design mode.
// return DesignerProperties.GetIsInDesignMode(element)
// || Application.Current == null
// || Application.Current.GetType() == typeof(Application);
//}
}
Change no. 3 - Modified BeginInvoke method in DefaultDispatcher.Desktop.cs as follow:
/// <summary>
/// Forwards the BeginInvoke to the current application's <see cref="Dispatcher"/>.
/// </summary>
/// <param name="method">Method to be invoked.</param>
/// <param name="arg">Arguments to pass to the invoked method.</param>
public void BeginInvoke(Delegate method, object arg)
{
if (Application.Current != null)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method, arg);
}
else if (InteropHelper.IsWindowsFormsApplication())
{
System.Windows.Forms.Application.OpenForms[0].BeginInvoke(method, arg);
}
else if (InteropHelper.FallBackDispatcherObject is Dispatcher)
{
((Dispatcher)InteropHelper.FallBackDispatcherObject).BeginInvoke(DispatcherPriority.Normal, method, arg);
}
else if (InteropHelper.FallBackDispatcherObject is System.Windows.Forms.Form)
{
((System.Windows.Forms.Form)InteropHelper.FallBackDispatcherObject).BeginInvoke(method, arg);
}
else if (InteropHelper.FallBackDispatcherObject is System.Windows.Forms.Control)
{
((System.Windows.Forms.Control)InteropHelper.FallBackDispatcherObject).BeginInvoke(method, arg);
}
}
Change no. 4 - Changed the DispatcherProxy class in WeakEventHandlerManager.Desktop.cs as follow:
/// <summary>
/// Hides the dispatcher mis-match between Silverlight and .Net, largely so code reads a bit easier
/// </summary>
private class DispatcherProxy
{
Dispatcher innerDispatcher;
private DispatcherProxy(Dispatcher dispatcher)
{
if (dispatcher != null)
{
innerDispatcher = dispatcher;
}
else if (InteropHelper.FallBackDispatcherObject !=null) //(WindowsFormHelper.IsWindowsFormsApplication())
{
if (InteropHelper.FallBackDispatcherObject is System.Windows.Threading.Dispatcher)
{
innerDispatcher = (System.Windows.Threading.Dispatcher)InteropHelper.FallBackDispatcherObject;
}
else
innerDispatcher = null;
}
}
public static DispatcherProxy CreateDispatcher()
{
DispatcherProxy proxy = null;
#if SILVERLIGHT
if (Deployment.Current == null)
return null;
proxy = new DispatcherProxy(Deployment.Current.Dispatcher);
#else
if (InteropHelper.FallBackDispatcherObject != null)
return new DispatcherProxy(null);
else if (InteropHelper.IsWindowsFormsApplication())
return new DispatcherProxy(null);
else if (Application.Current == null)
return null;
proxy = new DispatcherProxy(Application.Current.Dispatcher);
#endif
return proxy;
}
public bool CheckAccess()
{
if (innerDispatcher != null)
{
return innerDispatcher.CheckAccess();
}
else if (InteropHelper.IsWindowsFormsApplication())
{
return !System.Windows.Forms.Application.OpenForms[0].InvokeRequired;
}
else if (InteropHelper.FallBackDispatcherObject is System.Windows.Forms.Form)
{
return !((System.Windows.Forms.Form)InteropHelper.FallBackDispatcherObject).InvokeRequired;
}
else if (InteropHelper.FallBackDispatcherObject is System.Windows.Forms.Control)
{
return !((System.Windows.Forms.Control)InteropHelper.FallBackDispatcherObject).InvokeRequired;
}
return true;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Windows.Threading.Dispatcher.#BeginInvoke(System.Delegate,System.Windows.Threading.DispatcherPriority,System.Object[])")]
public DispatcherOperation BeginInvoke(Delegate method, params Object[] args)
{
#if SILVERLIGHT
return innerDispatcher.BeginInvoke(method, args);
#else
if (innerDispatcher != null)
{
return innerDispatcher.BeginInvoke(method, DispatcherPriority.Normal, args);
}
else if (InteropHelper.IsWindowsFormsApplication())
{
System.Windows.Forms.Application.OpenForms[0].BeginInvoke(method, args);
}
else if (InteropHelper.FallBackDispatcherObject is System.Windows.Forms.Form)
{
((System.Windows.Forms.Form)InteropHelper.FallBackDispatcherObject).BeginInvoke(method, args);
}
else if (InteropHelper.FallBackDispatcherObject is System.Windows.Forms.Control)
{
((System.Windows.Forms.Control)InteropHelper.FallBackDispatcherObject).BeginInvoke(method, args);
}
return null;
#endif
}
}