Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CustomValidationPopup: The specified Visual is not an ancestor of this Visual #4117

Closed
andyste1 opened this issue Jun 1, 2021 · 2 comments · Fixed by #4123
Closed

CustomValidationPopup: The specified Visual is not an ancestor of this Visual #4117

andyste1 opened this issue Jun 1, 2021 · 2 comments · Fixed by #4123
Labels
Milestone

Comments

@andyste1
Copy link

andyste1 commented Jun 1, 2021

I have a couple of TextBoxes within a Popup, which in turn resides in a custom control on my view. The TextBoxes are bound to VM properties - one int and one string. The binding on both TextBoxes use UpdateSourceTrigger=LostFocus. The Popup is opened via a button click (sets IsOpen = true).

If I open the popup, enter an invalid value into the int TextBox (e.g. "abc"), then tab to the second TextBox, the default MahApps validation error template appears as expected: a red border with a triangle in the top-right corner. If I tab back to the TextBox that is in error, an additional red "tooltip" appears to the right ("Value 'abc' could not be converted"), also as expected. However as soon as I type any character, valid or not (e.g. '1'), the following exception is thrown:-

System.InvalidOperationException
  HResult=0x80131509
  Message=The specified Visual is not an ancestor of this Visual.
  Source=PresentationCore
  StackTrace:
   at System.Windows.Media.Visual.TrySimpleTransformToAncestor(Visual ancestor, Boolean inverse, GeneralTransform& generalTransform, Matrix& simpleTransform)
   at System.Windows.Media.Visual.TransformToAncestor(Visual ancestor)
   at MahApps.Metro.Controls.CustomValidationPopup.IsElementVisible(FrameworkElement element, FrameworkElement container)
   at MahApps.Metro.Controls.CustomValidationPopup.ScrollViewer_ScrollChanged(Object sender, ScrollChangedEventArgs e)
   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.Controls.ScrollViewer.OnLayoutUpdated(Object sender, EventArgs e)
   at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(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 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at *****.App.Main()

  This exception was originally thrown at this call stack:
    [External Code]

It's a complex app/UI so isn't something I can include here to demonstrate the issue. I did try reproducing it in a standalone app but it worked fine, so it seems there are other factors involved, and is not simply due to having TextBoxes inside a Popup.

MahApps.Metro version: v2.4.5
Windows build number: Win10 v 10.0.19042
Visual Studio: 2019 16.9.5
Target Framework: .Net Framework v4.6

@andyste1 andyste1 added the Bug label Jun 1, 2021
@andyste1
Copy link
Author

andyste1 commented Jun 2, 2021

Looking at the source of CustomValidationPopup, I can see that it's trying to do a TransformToAncestor using a ScrollViewer. Based on this, I've now been able to create a simple repro (attached) by placing a Popup inside a ScrollViewer. (In the original app I have a ListBox, which will have an implicit ScrollViewer of course. Each ListBox item template contains a button that launches the Popup where I'm seeing the issue).

Run the attached app, enter something like 1.23 (a non-integer) into the first TextBox then tab to the second TextBox and enter the same value, at which point you should see the exception thrown.

MahAppsPopupTest.zip

Another observation: the width of the TextBox seems to have an effect. You'll notice those in the demo app are quite narrow. The problem doesn't seem to occur if you change them to (say) Width=50, so I'm guessing it has something to do with the text "scrolling" if more characters are typed than will fit.

@timunie
Copy link
Collaborator

timunie commented Jun 3, 2021

Hi @andyste1

Seems like you are on the right track about the ScrollViewer. With this information you can at least do the following workaround:

<Popup x:Name="Popup1"
       Placement="Mouse"
       StaysOpen="False">
       <!-- We add a scrollviewer and disable all scrolling -->
       <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled">

           <!--   YOUR CONTENT GOES HERE   -->

       </ScrollViewer>
</Popup>

P.S.: Please leave the ticket open as I think this should be fixed.

Happy coding
TIm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging a pull request may close this issue.

3 participants