Hosting an AvalonDock UserControl in WinForms

Aug 12, 2010 at 2:46 PM

Dear all,

I'm trying to create a WPF usercontrol that will be hosted in WinForms. When two DocumentContents are docked next to each other in the DocumentPane, and splitter between them is dragged, AvalonDock throws an exception.

Obviously, this behaviour is not exhibited when the code is run as a window in a WPF application.

(Incidently, the code below also illustrates the Autohide issue (Issue 11386).)

I am using v1.3.3571 on Windows 7 with .NET 4.0

Please find the exception and code I'm using below. Is this a bug, or am I doing something wrong?

Your help is greatly appreciated.

Regards,

JB

 

The exception is as follows:

System.ArgumentNullException was unhandled
  Message=Value cannot be null.
Parameter name: ancestor
  Source=PresentationCore
  ParamName=ancestor
  StackTrace:
       at System.Windows.Media.Visual.TransformToAncestor(Visual ancestor)
       at AvalonDock.ResizingPanel.splitter_DragDelta(Object sender, DragDeltaEventArgs e)
       at System.Windows.Controls.Primitives.DragDeltaEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
       at System.Windows.Controls.Primitives.Thumb.OnMouseMove(MouseEventArgs e)
       at System.Windows.UIElement.OnMouseMoveThunk(Object sender, MouseEventArgs e)
       at System.Windows.Input.MouseEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
       at System.Windows.Input.InputManager.ProcessStagingArea()
       at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
       at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
       at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at WindowsFormsTestApplication.Program.Main() in C:\Users\jburger\Documents\My Code\WindowsFormsTestApplication\WindowsFormsTestApplication\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

 

The usercontrol's XAML is as follows:

<UserControl x:Class="WindowsFormsTestApplication.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <ad:DockingManager>
        <ad:ResizingPanel Orientation="Horizontal">
            <ad:DockablePane>
                <ad:DockableContent x:Name="classesContent" Title="Classes" />
            </ad:DockablePane>
            <ad:DocumentPane>
                <ad:DocumentContent Title="MyFirstDocument" />
                <ad:DocumentContent Title="MySecondDocument" />
            </ad:DocumentPane>
        </ad:ResizingPanel>
    </ad:DockingManager>
</UserControl>

Aug 13, 2010 at 1:27 PM

Dear all,

It seems as though the issue is that the Window.GetWindow() method returns a null when WPF code is hosted in a WinForms application.

I have replaced the GetWindow() methods on lines 884 and 1174 with the following code, and it seems to work. This also looks like it should solve issue # 11386 with some massaging. Do you guys see any reason why I shouldn't use this?

Thanks in advance!

Regards,

JB

private Visual GetParent()
{
    DependencyObject parent = this.Parent;
    while (!(parent is Visual))
    {
        parent = LogicalTreeHelper.GetParent(parent);
    }
    return (Visual)parent;
}