From 8938e3ea5a049ebc3bd279709495d0b7dc5029df Mon Sep 17 00:00:00 2001 From: Bastian Schmidt Date: Wed, 3 Jul 2019 21:14:32 +0200 Subject: [PATCH] Fixing validation adorner for not yet visible controls --- .../System/Windows/Controls/Validation.cs | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Validation.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Validation.cs index 76b6af9df20..bfbd04cc1ab 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Validation.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Validation.cs @@ -345,7 +345,6 @@ private static void OnValidationAdornerSiteForChanged(DependencyObject d, Depend } } - internal static void ShowValidationAdorner(DependencyObject targetElement, bool show) { // If the element has a VisualStateGroup for validation, then dont show the Adorner @@ -363,7 +362,6 @@ internal static void ShowValidationAdorner(DependencyObject targetElement, bool } } - private static bool HasValidationGroup(FrameworkElement fe) { if (fe != null) @@ -420,6 +418,26 @@ private static object ShowValidationAdornerOperation(object arg) return null; } + private static void ShowValidationAdornerWhenAdornerSiteGetsVisible(object sender, DependencyPropertyChangedEventArgs e) + { + var adornerSite = sender as UIElement; + + if (adornerSite == null) + { + return; + } + + adornerSite.IsVisibleChanged -= ShowValidationAdornerOnVisible; + + DependencyObject targetElement = GetValidationAdornerSiteFor(adornerSite); + if (targetElement == null) + { + targetElement = adornerSite; + } + + ShowValidationAdornerHelper(targetElement, adornerSite, (bool)e.NewValue && GetHasError(targetElement), false); + } + private static void ShowValidationAdornerHelper(DependencyObject targetElement, DependencyObject adornerSite, bool show, bool tryAgain) { UIElement siteUIElement = adornerSite as UIElement; @@ -432,10 +450,19 @@ private static void ShowValidationAdornerHelper(DependencyObject targetElement, { if (tryAgain) { - // try again later, perhaps giving layout a chance to create the adorner layer - adornerSite.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, - new DispatcherOperationCallback(ShowValidationAdornerOperation), - new object[]{targetElement, adornerSite, show}); + // Check if the element is visible, if not try to show the adorner again once it gets visible. + // This is needed because controls hosted in Expander or TabControl don't have a parent/AdornerLayer till the Expander is expanded or the TabItem is selected. + if (siteUIElement.IsVisible == false) + { + siteUIElement.IsVisibleChanged += ShowValidationAdornerWhenAdornerSiteGetsVisible; + } + else + { + // try again later, perhaps giving layout a chance to create the adorner layer + adornerSite.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, + new DispatcherOperationCallback(ShowValidationAdornerOperation), + new object[]{targetElement, adornerSite, show}); + } } return; }