From 8c992b2bcfd9a05131cdec4f8098ee0a705ab656 Mon Sep 17 00:00:00 2001 From: punker76 Date: Thu, 10 Jun 2021 16:37:27 +0200 Subject: [PATCH 1/2] Merge pull request #4122 from MahApps/fix/4120 Fix position of ValidationErrorTemplate together with ValidatesOnExceptions --- .../MahApps.Metro.Demo/ExampleViews/TextExamples.xaml | 2 +- src/MahApps.Metro/Controls/CustomValidationPopup.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml index cac99344a6..16dfeff62e 100644 --- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml +++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml @@ -159,7 +159,7 @@ Style="{DynamicResource MahApps.Styles.TextBox.Button}" /> + Text="{Binding IntegerGreater10Property, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True}" /> diff --git a/src/MahApps.Metro/Controls/CustomValidationPopup.cs b/src/MahApps.Metro/Controls/CustomValidationPopup.cs index 5582f5779f..a9c1e2dc8b 100644 --- a/src/MahApps.Metro/Controls/CustomValidationPopup.cs +++ b/src/MahApps.Metro/Controls/CustomValidationPopup.cs @@ -260,10 +260,10 @@ private void OnTransitionCompleted(object sender, RoutedEventArgs e) private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { - this.RefreshPosition(); - if (e.VerticalChange > 0 || e.VerticalChange < 0 || e.HorizontalChange > 0 || e.HorizontalChange < 0) { + this.RefreshPosition(); + if (IsElementVisible(this.AdornedElement as FrameworkElement, this.scrollViewer)) { var adornedElement = this.AdornedElement; From 39ba5fa78cd3f1f2e7c3c8b4475282cd7781d614 Mon Sep 17 00:00:00 2001 From: punker76 Date: Thu, 10 Jun 2021 16:38:30 +0200 Subject: [PATCH 2/2] Merge pull request #4123 from MahApps/fix/4117 Fix getting the wrong Ancestor (ScrollViewer) at CustomValidationPopup --- .../Controls/CustomValidationPopup.cs | 2 +- src/MahApps.Metro/Controls/TreeHelper.cs | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/MahApps.Metro/Controls/CustomValidationPopup.cs b/src/MahApps.Metro/Controls/CustomValidationPopup.cs index a9c1e2dc8b..a0bf4bd529 100644 --- a/src/MahApps.Metro/Controls/CustomValidationPopup.cs +++ b/src/MahApps.Metro/Controls/CustomValidationPopup.cs @@ -144,7 +144,7 @@ private void CustomValidationPopup_Loaded(object sender, RoutedEventArgs e) this.scrollViewer.ScrollChanged -= this.ScrollViewer_ScrollChanged; } - this.scrollViewer = adornedElement.TryFindParent(); + this.scrollViewer = adornedElement.GetVisualAncestor(); if (this.scrollViewer != null) { this.scrollViewer.ScrollChanged += this.ScrollViewer_ScrollChanged; diff --git a/src/MahApps.Metro/Controls/TreeHelper.cs b/src/MahApps.Metro/Controls/TreeHelper.cs index e2709a2132..a1dd894fdb 100644 --- a/src/MahApps.Metro/Controls/TreeHelper.cs +++ b/src/MahApps.Metro/Controls/TreeHelper.cs @@ -58,6 +58,47 @@ public static IEnumerable GetAncestors(this DependencyObject c } } + /// + /// Returns full visual ancestry, starting at the leaf. + /// If element is not of or the logical ancestry is used. + /// + /// The starting object. + /// + public static IEnumerable GetVisualAncestry(this DependencyObject? leaf) + { + while (leaf != null) + { + yield return leaf; + leaf = leaf is Visual || leaf is Visual3D + ? VisualTreeHelper.GetParent(leaf) + : LogicalTreeHelper.GetParent(leaf); + } + } + + /// + /// Tries to find and returns a visual ancestor, starting at the leaf. + /// If element is not of or the logical ancestry is used. + /// + /// The starting object. + /// + public static T GetVisualAncestor(this DependencyObject? leaf) + where T : DependencyObject + { + while (leaf != null) + { + if (leaf is T ancestor) + { + return ancestor; + } + + leaf = leaf is Visual || leaf is Visual3D + ? VisualTreeHelper.GetParent(leaf) + : LogicalTreeHelper.GetParent(leaf); + } + + return default(T); + } + /// /// Finds a Child of a given item in the visual tree. ///