未验证 提交 e80b23b7 编写于 作者: B Bastian Schmidt 提交者: GitHub

Fixing validation adorner for not yet visible controls (#1167)

* Fixing validation adorner for not yet visible controls

* Using "is" pattern

* Moving visibility check to ShowValidationAdornerOperation
上级 68ba2fa8
......@@ -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)
......@@ -415,60 +413,86 @@ private static object ShowValidationAdornerOperation(object arg)
DependencyObject adornerSite = (DependencyObject)args[1];
bool show = (bool)args[2];
ShowValidationAdornerHelper(targetElement, adornerSite, show, false);
// 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 (adornerSite is UIElement { IsVisible: false } siteUIElement)
{
siteUIElement.IsVisibleChanged += ShowValidationAdornerWhenAdornerSiteGetsVisible;
}
else
{
ShowValidationAdornerHelper(targetElement, adornerSite, show, false);
}
return null;
}
private static void ShowValidationAdornerHelper(DependencyObject targetElement, DependencyObject adornerSite, bool show, bool tryAgain)
private static void ShowValidationAdornerWhenAdornerSiteGetsVisible(object sender, DependencyPropertyChangedEventArgs e)
{
UIElement siteUIElement = adornerSite as UIElement;
if (sender is not UIElement adornerSite)
{
return;
}
adornerSite.IsVisibleChanged -= ShowValidationAdornerWhenAdornerSiteGetsVisible;
if (siteUIElement != null)
DependencyObject targetElement = GetValidationAdornerSiteFor(adornerSite);
if (targetElement == null)
{
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(siteUIElement);
targetElement = adornerSite;
}
if (adornerLayer == null)
{
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});
}
return;
}
ShowValidationAdornerHelper(targetElement, adornerSite, (bool)e.NewValue && GetHasError(targetElement), false);
}
private static void ShowValidationAdornerHelper(DependencyObject targetElement, DependencyObject adornerSite, bool show, bool tryAgain)
{
if (adornerSite is not UIElement siteUIElement)
{
return;
}
TemplatedAdorner validationAdorner = siteUIElement.ReadLocalValue(ValidationAdornerProperty) as TemplatedAdorner;
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(siteUIElement);
if (show && validationAdorner == null)
if (adornerLayer is null)
{
if (tryAgain)
{
// get the template from the site, or from the target element
ControlTemplate validationTemplate = GetErrorTemplate(siteUIElement);
if (validationTemplate == null)
{
validationTemplate = GetErrorTemplate(targetElement);
}
// 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, BooleanBoxes.Box(show) });
}
return;
}
if (validationTemplate != null)
{
validationAdorner = new TemplatedAdorner(siteUIElement, validationTemplate);
adornerLayer.Add(validationAdorner);
TemplatedAdorner validationAdorner = siteUIElement.ReadLocalValue(ValidationAdornerProperty) as TemplatedAdorner;
siteUIElement.SetValue(ValidationAdornerProperty, validationAdorner);
}
if (show && validationAdorner is null)
{
// get the template from the site, or from the target element
ControlTemplate validationTemplate = GetErrorTemplate(siteUIElement);
if (validationTemplate is null)
{
validationTemplate = GetErrorTemplate(targetElement);
}
else if (!show && validationAdorner != null)
if (validationTemplate is not null)
{
validationAdorner.ClearChild();
adornerLayer.Remove(validationAdorner);
siteUIElement.ClearValue(ValidationAdornerProperty);
validationAdorner = new TemplatedAdorner(siteUIElement, validationTemplate);
adornerLayer.Add(validationAdorner);
siteUIElement.SetValue(ValidationAdornerProperty, validationAdorner);
}
}
else if (!show && validationAdorner is not null)
{
validationAdorner.ClearChild();
adornerLayer.Remove(validationAdorner);
siteUIElement.ClearValue(ValidationAdornerProperty);
}
}
/// <summary>
/// Mark this BindingExpression as invalid. If the BindingExpression has been
/// explicitly marked invalid in this way, then it will remain
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册