From 58b648b40c8610b291a7969b6970ea5b9d22ed25 Mon Sep 17 00:00:00 2001 From: brianlagunas_cp Date: Sat, 12 Feb 2011 03:43:33 +0000 Subject: [PATCH] ChildWIndow: fixed bug which was cause by showing the window then resizing the parent, the window would not recalculate its position to stay in view. I refactored the code. I also added a new property called WindowStartupLocation. There are two options; Center and Manual. Set it to Center if you want the ChildWindow to always be centered when it opens. Set it to Manual if you want to control where it opens by setting the Top and Left properties. If set on Manual and the user drags the ChildWindow and closes it, it will reopen the last place the user moved it. The default value is Manual. --- .../ChildWindow/ChildWindow.cs | 146 +++++++++++------- .../ChildWindow/WindowStartupLocation.cs | 10 ++ .../ChildWindow/WindowState.cs | 5 +- .../WPFToolkit.Extended/Themes/Generic.xaml | 2 +- .../WPFToolkit.Extended.csproj | 1 + 5 files changed, 101 insertions(+), 63 deletions(-) create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowStartupLocation.cs diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs index 01b81462..6f645665 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs @@ -64,11 +64,12 @@ namespace Microsoft.Windows.Controls if (CloseButton != null) CloseButton.Click += (o, e) => Close(); - //Overlay = GetTemplateChild("PART_Overlay") as Panel; WindowRoot = GetTemplateChild("PART_WindowRoot") as Grid; WindowRoot.RenderTransform = _moveTransform; _parentContainer = VisualTreeHelper.GetParent(this) as FrameworkElement; + _parentContainer.LayoutUpdated += ParentContainer_LayoutUpdated; + _parentContainer.SizeChanged += ParentContainer_SizeChanged; //this is for XBAP applications only. When inside an XBAP the parent container has no height or width until it has loaded. Therefore //we need to handle the loaded event and reposition the window. @@ -76,17 +77,10 @@ namespace Microsoft.Windows.Controls { _parentContainer.Loaded += (o, e) => { - CenterChildWindow(); + ExecuteOpen(); }; } - _parentContainer.LayoutUpdated += ParentContainer_LayoutUpdated; - _parentContainer.SizeChanged += (o, ea) => - { - _modalLayer.Height = ea.NewSize.Height; - _modalLayer.Width = ea.NewSize.Width; - }; - _root = GetTemplateChild("Root") as Grid; Style focusStyle = _root.Resources["FocusVisualStyle"] as Style; @@ -195,7 +189,7 @@ namespace Microsoft.Windows.Controls private static void OnIsModalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - ChildWindow childWindow = (ChildWindow)d; + ChildWindow childWindow = d as ChildWindow; if (childWindow != null) childWindow.OnIsModalChanged((bool)e.OldValue, (bool)e.NewValue); } @@ -227,9 +221,15 @@ namespace Microsoft.Windows.Controls private static void OnLeftPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { - ChildWindow window = (ChildWindow)obj; - window.Left = window.GetRestrictedLeft(); - window.ProcessMove((double)e.NewValue - (double)e.OldValue, 0); + ChildWindow childWindow = obj as ChildWindow; + if (childWindow != null) + childWindow.OnLeftPropertyChanged((double)e.OldValue, (double)e.NewValue); + } + + private void OnLeftPropertyChanged(double oldValue, double newValue) + { + Left = GetRestrictedLeft(); + ProcessMove(newValue - oldValue, 0); } #endregion //Left @@ -267,9 +267,15 @@ namespace Microsoft.Windows.Controls private static void OnTopPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { - ChildWindow window = (ChildWindow)obj; - window.Top = window.GetRestrictedTop(); - window.ProcessMove(0, (double)e.NewValue - (double)e.OldValue); + ChildWindow childWindow = obj as ChildWindow; + if (childWindow != null) + childWindow.OnTopPropertyChanged((double)e.OldValue, (double)e.NewValue); + } + + private void OnTopPropertyChanged(double oldValue, double newValue) + { + Top = GetRestrictedTop(); + ProcessMove(0, newValue - oldValue); } #endregion //TopProperty @@ -295,6 +301,29 @@ namespace Microsoft.Windows.Controls set { SetValue(WindowOpacityProperty, value); } } + #region WindowStartupLocation + + public static readonly DependencyProperty WindowStartupLocationProperty = DependencyProperty.Register("WindowStartupLocation", typeof(WindowStartupLocation), typeof(ChildWindow), new UIPropertyMetadata(WindowStartupLocation.Manual, OnWindowStartupLocationChanged)); + public WindowStartupLocation WindowStartupLocation + { + get { return (WindowStartupLocation)GetValue(WindowStartupLocationProperty); } + set { SetValue(WindowStartupLocationProperty, value); } + } + + private static void OnWindowStartupLocationChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ChildWindow childWindow = o as ChildWindow; + if (childWindow != null) + childWindow.OnWindowStartupLocationChanged((WindowStartupLocation)e.OldValue, (WindowStartupLocation)e.NewValue); + } + + protected virtual void OnWindowStartupLocationChanged(WindowStartupLocation oldValue, WindowStartupLocation newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //WindowStartupLocation + #region WindowState public static readonly DependencyProperty WindowStateProperty = DependencyProperty.Register("WindowState", typeof(WindowState), typeof(ChildWindow), new PropertyMetadata(WindowState.Open, new PropertyChangedCallback(OnWindowStatePropertyChanged))); @@ -386,11 +415,22 @@ namespace Microsoft.Windows.Controls //we only want to set the start position if this is the first time the control has bee initialized if (!_startupPositionInitialized) { - SetStartupPosition(); + ExecuteOpen(); _startupPositionInitialized = true; } } + void ParentContainer_SizeChanged(object sender, SizeChangedEventArgs e) + { + //resize our modal layer + _modalLayer.Height = e.NewSize.Height; + _modalLayer.Width = e.NewSize.Width; + + //reposition our window + Left = GetRestrictedLeft(); + Top = GetRestrictedTop(); + } + #endregion //Event Handlers #region Methods @@ -399,16 +439,15 @@ namespace Microsoft.Windows.Controls private double GetRestrictedLeft() { + if (Left < 0) + return 0; + if (_parentContainer != null) { - if (Left < 0) - { - return 0; - } - if (Left + WindowRoot.ActualWidth > _parentContainer.ActualWidth && _parentContainer.ActualWidth != 0) { - return _parentContainer.ActualWidth - WindowRoot.ActualWidth; + double left = _parentContainer.ActualWidth - WindowRoot.ActualWidth; + return left < 0 ? 0 : left; } } @@ -417,16 +456,15 @@ namespace Microsoft.Windows.Controls private double GetRestrictedTop() { + if (Top < 0) + return 0; + if (_parentContainer != null) { - if (Top < 0) - { - return 0; - } - if (Top + WindowRoot.ActualHeight > _parentContainer.ActualHeight && _parentContainer.ActualHeight != 0) { - return _parentContainer.ActualHeight - WindowRoot.ActualHeight; + double top = _parentContainer.ActualHeight - WindowRoot.ActualHeight; + return top < 0 ? 0 : top; } } @@ -466,13 +504,17 @@ namespace Microsoft.Windows.Controls } else { - _dialogResult = null; //if the Close is cancelled, DialogResult should always be NULL: + _dialogResult = null; //if the Close is cancelled, DialogResult should always be null } } private void ExecuteOpen() { _dialogResult = null; //reset the dialogResult to null each time the window is opened + + if (WindowStartupLocation == Controls.WindowStartupLocation.Center) + CenterChildWindow(); + BringToFront(); } @@ -481,28 +523,16 @@ namespace Microsoft.Windows.Controls int index = 0; if (_parentContainer != null) - { index = (int)_parentContainer.GetValue(Canvas.ZIndexProperty); - } - this.SetValue(Canvas.ZIndexProperty, ++index); + SetValue(Canvas.ZIndexProperty, ++index); if (IsModal) - { Canvas.SetZIndex(_modalLayerPanel, -1); - } - } - - private void SetStartupPosition() - { - CenterChildWindow(); - BringToFront(); } private void CenterChildWindow() { - _moveTransform.X = _moveTransform.Y = 0; - if (_parentContainer != null) { Left = (_parentContainer.ActualWidth - WindowRoot.ActualWidth) / 2.0; @@ -510,18 +540,6 @@ namespace Microsoft.Windows.Controls } } - protected virtual void ChangeVisualState() - { - if (WindowState == WindowState.Closed) - { - VisualStateManager.GoToState(this, VisualStates.Closed, true); - } - else - { - VisualStateManager.GoToState(this, VisualStates.Open, true); - } - } - private void ShowModalLayer() { if (!DesignerProperties.GetIsInDesignMode(this)) @@ -539,14 +557,26 @@ namespace Microsoft.Windows.Controls _modalLayerPanel.Children.Remove(_modalLayer); } + private void ProcessMove(double x, double y) + { + _moveTransform.X += x; + _moveTransform.Y += y; + } + #endregion //Private #region Protected - protected void ProcessMove(double x, double y) + protected virtual void ChangeVisualState() { - _moveTransform.X += x; - _moveTransform.Y += y; + if (WindowState == WindowState.Closed) + { + VisualStateManager.GoToState(this, VisualStates.Closed, true); + } + else + { + VisualStateManager.GoToState(this, VisualStates.Open, true); + } } #endregion //Protected diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowStartupLocation.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowStartupLocation.cs new file mode 100644 index 00000000..e212e837 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowStartupLocation.cs @@ -0,0 +1,10 @@ +using System; + +namespace Microsoft.Windows.Controls +{ + public enum WindowStartupLocation + { + Center, + Manual + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowState.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowState.cs index cc001a25..c5055e8d 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowState.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/WindowState.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Microsoft.Windows.Controls { @@ -10,4 +7,4 @@ namespace Microsoft.Windows.Controls Closed, Open } -} +} \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index 4f3f7a1a..4de0dfee 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -526,7 +526,7 @@ - + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index 0dbfc2c0..d17ec715 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -67,6 +67,7 @@ +