WPF的悬停工具栏实现方案
解决方法:参照ToolTip控件实现一个功能更为强大的ToolTip(命名为RichToolTip)
1、目标:仿照Word2007的悬停工具栏,如下图实现上下文工具栏。
2、虽然ToolTip的控件模板可以定义为包含可交互操作的控件(如Button,TextBox等),然而却无法接受焦点(鼠标移到ToolTip上内容立即就消失),所以无法用此办法实现;
3、使用方法与ToolTipService类似,参见如下代码:
<TextBox x:Name="_txtWords" BorderThickness="1" BorderBrush="Black" Margin="5"> <controls:RichToolTip.PopupContent> <controls:RichToolTip PlacementTarget="{Binding RelativeSource={RelativeSource Self}, Path=RelatedObject}" Placement="MousePoint" HorizontalOffset="0" VerticalOffset="0"> <Border BorderBrush="Black" BorderThickness="1" Margin="5" Background="DarkKhaki"> <utils:HoverOverToolBarView /> </Border> </controls:RichToolTip> </controls:RichToolTip.PopupContent> </TextBox>
4、应用效果如下所见:
5、代码实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Windows; 5 using System.Windows.Controls; 6 using System.Windows.Controls.Primitives; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Shapes; 13 using System.Windows.Threading; 14 using System.Runtime.InteropServices; 15 using System.Windows.Interop; 16 using System.Reflection; 17 using System.Diagnostics; 18 using System.Security; 19 using System.Security.Permissions; 20 using System.Windows.Navigation; 21 using System.Windows.Media.Animation; 22 23 namespace JetSun.Presentation.Controls 24 { 25 /// <summary> 26 /// A kind-of Tooltip implementation that stays open once element is hovered and the content inside is responsive 27 /// 28 /// It corresponds to most of the TooltipService attached properties so use them as you wish 29 /// Known Issues: 30 /// 1 - I didn't have the time nor the strength to care about repositioning. I simply hide the popup whenever it would need repositioning. (Window movement, etc..) But it's ok since it's the default behavior of popup overall. 31 /// 2 - XBap mode sets transparency through a hack! supported only in full trust. 32 /// 3 - In XBap mode, moving the mouse slowly towards the popup will cause it to hide 33 /// 4 - In XBap mode, moving the mouse over the element shows the tooltip even when the browser isn't the active window 34 /// </summary> 35 /// 36 public partial class RichToolTip : ContentControl 37 { 38 #region Fields 39 const int _animationDurationInMs = 200; 40 const int _showDeferredMilliseconds = 500; 41 const bool _animationEnabledDefault = true; 42 43 delegate void Action(); 44 Popup _parentPopup; 45 46 static RichToolTip _lastShownPopup = null; 47 #endregion 48 49 #region Properties 50 UIElement _relatedObject; 51 /// <summary> 52 /// 关联控件 53 /// </summary> 54 public UIElement RelatedObject 55 { 56 get { return _relatedObject; } 57 } 58 59 private bool _enableAnimation = _animationEnabledDefault; 60 /// <summary> 61 /// 是否显示动画 62 /// </summary> 63 public bool EnableAnimation 64 { 65 get { return _enableAnimation; } 66 set { _enableAnimation = value; } 67 } 68 #endregion 69 70 #region Instancing 71 static RichToolTip() 72 { 73 EventManager.RegisterClassHandler(typeof(UIElement), UIElement.MouseDownEvent, new MouseButtonEventHandler(OnElementMouseDown), true); 74 EventManager.RegisterClassHandler(typeof(RichToolTip), ButtonBase.ClickEvent, new RoutedEventHandler(OnButtonBaseClick), false); 75 EventManager.RegisterClassHandler(typeof(Selector), Selector.SelectionChangedEvent, new SelectionChangedEventHandler(selector_SelectionChangedEvent), true); 76 77 if (BrowserInteropHelper.IsBrowserHosted) 78 { 79 EventManager.RegisterClassHandler(typeof(NavigationWindow), UIElement.MouseLeaveEvent, new RoutedEventHandler(OnNavigationWindowMouseLeaveEvent), true); 80 } 81 else 82 { 83 EventManager.RegisterClassHandler(typeof(Window), Window.SizeChangedEvent, new RoutedEventHandler(OnWindowSizeChanged), true); 84 } 85 86 CommandManager.RegisterClassCommandBinding(typeof(RichToolTip), new CommandBinding(CloseCommand, ExecuteCloseCommand)); 87 InitStoryboards(); 88 } 89 /// <summary> 90 /// 91 /// </summary> 92 public RichToolTip() 93 { 94 Loaded += new RoutedEventHandler(ContentTooltip_Loaded); 95 Unloaded += new RoutedEventHandler(ContentTooltip_Unloaded); 96 } 97 /// <summary> 98 /// 99 /// </summary> 100 /// <param name="relatedObject"></param> 101 public RichToolTip(UIElement relatedObject) 102 : this() 103 { 104 Load(relatedObject); 105 } 106 #endregion 107 108 #region Loading 109 void Load(UIElement relatedObject) 110 { 111 _relatedObject = relatedObject; 112 113 FrameworkElement fe = relatedObject as FrameworkElement; 114 115 if (fe == null) 116 { 117 throw new InvalidOperationException("The element is not supported"); 118 } 119 120 _relatedObject.MouseEnter += element_MouseEnter; 121 _relatedObject.MouseLeave += element_MouseLeave; 122 123 fe.Unloaded += new RoutedEventHandler(RelatedObject_Unloaded); 124 125 BindRootVisual(); 126 127 this.MouseLeave += new MouseEventHandler(RichToolTip_MouseLeave); 128 } 129 130 void RichToolTip_MouseLeave(object sender, MouseEventArgs e) 131 { 132 if (IsShown() && this == _lastShownPopup) 133 { 134 Hide(true); 135 } 136 } 137 138 void RelatedObject_Unloaded(object sender, RoutedEventArgs e) 139 { 140 _relatedObject.MouseEnter -= element_MouseEnter; 141 _relatedObject.MouseLeave -= element_MouseLeave; 142 } 143 144 void ContentTooltip_Unloaded(object sender, RoutedEventArgs e) 145 { 146 UnbindRootVisual(); 147 } 148 149 void ContentTooltip_Loaded(object sender, RoutedEventArgs e) 150 { 151 BindRootVisual(); 152 } 153 #endregion 154 155 #region Popup Creation 156 private static readonly Type PopupType = typeof(Popup); 157 private static readonly Type PopupSecurityHelperType = PopupType.GetNestedType("PopupSecurityHelper", BindingFlags.Public | BindingFlags.NonPublic); 158 159 private static readonly FieldInfo Popup_secHelper = PopupType.GetField("_secHelper", BindingFlags.Instance | BindingFlags.NonPublic); 160 private static readonly FieldInfo PopupSecurityHelper_isChildPopupInitialized = PopupSecurityHelperType.GetField("_isChildPopupInitialized", BindingFlags.Instance | BindingFlags.NonPublic); 161 private static readonly FieldInfo PopupSecurityHelper_isChildPopup = PopupSecurityHelperType.GetField("_isChildPopup", BindingFlags.Instance | BindingFlags.NonPublic); 162 163 void HookupParentPopup() 164 { 165 _parentPopup = new Popup(); 166 167 if (BrowserInteropHelper.IsBrowserHosted) 168 { 169 try 170 { 171 new ReflectionPermission(PermissionState.Unrestricted).Demand(); 172 173 DoPopupHacks(); 174 } 175 catch (SecurityException) { } 176 } 177 178 _parentPopup.AllowsTransparency = true; 179 Popup.CreateRootPopup(_parentPopup, this); 180 } 181 182 void DoPopupHacks() 183 { 184 object secHelper = Popup_secHelper.GetValue(_parentPopup); 185 PopupSecurityHelper_isChildPopupInitialized.SetValue(secHelper, true); 186 PopupSecurityHelper_isChildPopup.SetValue(secHelper, false); 187 } 188 #endregion 189 190 #region Commands 191 /// <summary> 192 /// 193 /// </summary> 194 public static RoutedCommand CloseCommand = new RoutedCommand("Close", typeof(RichToolTip)); 195 static void ExecuteCloseCommand(object sender, ExecutedRoutedEventArgs e) 196 { 197 HideLastShown(true); 198 } 199 #endregion 200 201 #region Dependency Properties 202 /// <summary> 203 /// 204 /// </summary> 205 public static readonly DependencyProperty PlacementProperty = ToolTipService.PlacementProperty.AddOwner(typeof(RichToolTip)); 206 /// <summary> 207 /// 208 /// </summary> 209 public PlacementMode Placement 210 { 211 get { return (PlacementMode)GetValue(PlacementProperty); } 212 set { SetValue(PlacementProperty, value); } 213 } 214 /// <summary> 215 /// 216 /// </summary> 217 /// <param name="obj"></param> 218 /// <returns></returns> 219 public static PlacementMode GetPlacement(DependencyObject obj) 220 { 221 return (PlacementMode)obj.GetValue(PlacementProperty); 222 } 223 /// <summary> 224 /// 225 /// </summary> 226 /// <param name="obj"></param> 227 /// <param name="value"></param> 228 public static void SetPlacement(DependencyObject obj, PlacementMode value) 229 { 230 obj.SetValue(PlacementProperty, value); 231 } 232 /// <summary> 233 /// 234 /// </summary> 235 public static readonly DependencyProperty PlacementTargetProperty = ToolTipService.PlacementTargetProperty.AddOwner(typeof(RichToolTip)); 236 /// <summary> 237 /// 238 /// </summary> 239 public UIElement PlacementTarget 240 { 241 get { return (UIElement)GetValue(PlacementTargetProperty); } 242 set { SetValue(PlacementTargetProperty, value); } 243 } 244 /// <summary> 245 /// 246 /// </summary> 247 /// <param name="obj"></param> 248 /// <returns></returns> 249 public static UIElement GetPlacementTarget(DependencyObject obj) 250 { 251 return (UIElement)obj.GetValue(PlacementTargetProperty); 252 } 253 /// <summary> 254 /// 255 /// </summary> 256 /// <param name="obj"></param> 257 /// <param name="value"></param> 258 public static void SetPlacementTarget(DependencyObject obj, UIElement value) 259 { 260 obj.SetValue(PlacementTargetProperty, value); 261 } 262 /// <summary> 263 /// 264 /// </summary> 265 public static readonly DependencyProperty PlacementRectangleProperty = ToolTipService.PlacementRectangleProperty.AddOwner(typeof(RichToolTip)); 266 /// <summary> 267 /// 268 /// </summary> 269 public Rect PlacementRectangle 270 { 271 get { return (Rect)GetValue(PlacementRectangleProperty); } 272 set { SetValue(PlacementRectangleProperty, value); } 273 } 274 /// <summary> 275 /// 276 /// </summary> 277 /// <param name="obj"></param> 278 /// <returns></returns> 279 public static Rect GetPlacementRectangle(DependencyObject obj) 280 { 281 return (Rect)obj.GetValue(PlacementRectangleProperty); 282 } 283 /// <summary> 284 /// 285 /// </summary> 286 /// <param name="obj"></param> 287 /// <param name="value"></param> 288 public static void SetPlacementRectangle(DependencyObject obj, Rect value) 289 { 290 obj.SetValue(PlacementRectangleProperty, value); 291 } 292 /// <summary> 293 /// 294 /// </summary> 295 public static readonly DependencyProperty HorizontalOffsetProperty = ToolTipService.HorizontalOffsetProperty.AddOwner(typeof(RichToolTip)); 296 /// <summary> 297 /// 298 /// </summary> 299 public double HorizontalOffset 300 { 301 get { return (double)GetValue(HorizontalOffsetProperty); } 302 set { SetValue(HorizontalOffsetProperty, value); } 303 } 304 /// <summary> 305 /// 306 /// </summary> 307 /// <param name="obj"></param> 308 /// <returns></returns> 309 public static double GetHorizontalOffset(DependencyObject obj) 310 { 311 return (double)obj.GetValue(HorizontalOffsetProperty); 312 } 313 /// <summary> 314 /// 315 /// </summary> 316 /// <param name="obj"></param> 317 /// <param name="value"></param> 318 public static void SetHorizontalOffset(DependencyObject obj, double value) 319 { 320 obj.SetValue(HorizontalOffsetProperty, value); 321 } 322 /// <summary> 323 /// 324 /// </summary> 325 public static readonly DependencyProperty VerticalOffsetProperty = ToolTipService.VerticalOffsetProperty.AddOwner(typeof(RichToolTip)); 326 /// <summary> 327 /// 328 /// </summary> 329 public double VerticalOffset 330 { 331 get { return (double)GetValue(VerticalOffsetProperty); } 332 set { SetValue(VerticalOffsetProperty, value); } 333 } 334 /// <summary> 335 /// 336 /// </summary> 337 /// <param name="obj"></param> 338 /// <returns></returns> 339 public static double GetVerticalOffset(DependencyObject obj) 340 { 341 return (double)obj.GetValue(VerticalOffsetProperty); 342 } 343 /// <summary> 344 /// 345 /// </summary> 346 /// <param name="obj"></param> 347 /// <param name="value"></param> 348 public static void SetVerticalOffset(DependencyObject obj, double value) 349 { 350 obj.SetValue(VerticalOffsetProperty, value); 351 } 352 /// <summary> 353 /// 354 /// </summary> 355 public static readonly DependencyProperty IsOpenProperty = 356 Popup.IsOpenProperty.AddOwner(typeof(RichToolTip), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnIsOpenChanged))); 357 /// <summary> 358 /// 359 /// </summary> 360 public bool IsOpen 361 { 362 get { return (bool)GetValue(IsOpenProperty); } 363 set { SetValue(IsOpenProperty, value); } 364 } 365 366 private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 367 { 368 RichToolTip ctrl = (RichToolTip)d; 369 370 if ((bool)e.NewValue) 371 { 372 if (ctrl._parentPopup == null) 373 { 374 ctrl.HookupParentPopup(); 375 } 376 } 377 } 378 379 #endregion 380 381 #region Attached Properties 382 383 #region HideOnClick 384 /// <summary> 385 /// 386 /// </summary> 387 /// <param name="obj"></param> 388 /// <returns></returns> 389 public static bool GetHideOnClick(DependencyObject obj) 390 { 391 return (bool)obj.GetValue(HideOnClickProperty); 392 } 393 /// <summary> 394 /// 395 /// </summary> 396 /// <param name="obj"></param> 397 /// <param name="value"></param> 398 public static void SetHideOnClick(DependencyObject obj, bool value) 399 { 400 obj.SetValue(HideOnClickProperty, value); 401 } 402 /// <summary> 403 /// 404 /// </summary> 405 public static readonly DependencyProperty HideOnClickProperty = 406 DependencyProperty.RegisterAttached("HideOnClick", typeof(bool), typeof(RichToolTip), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits)); 407 #endregion 408 409 #region PopupContent 410 /// <summary> 411 /// 412 /// </summary> 413 /// <param name="obj"></param> 414 /// <returns></returns> 415 public static object GetPopupContent(DependencyObject obj) 416 { 417 return obj.GetValue(PopupContentProperty); 418 } 419 /// <summary> 420 /// 421 /// </summary> 422 /// <param name="obj"></param> 423 /// <param name="value"></param> 424 public static void SetPopupContent(DependencyObject obj, object value) 425 { 426 obj.SetValue(PopupContentProperty, value); 427 } 428 /// <summary> 429 /// 430 /// </summary> 431 public static readonly DependencyProperty PopupContentProperty = 432 DependencyProperty.RegisterAttached("PopupContent", typeof(object), typeof(RichToolTip), new FrameworkPropertyMetadata(OnPopupContentChanged)); 433 434 private static void OnPopupContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 435 { 436 UIElement element = o as UIElement; 437 if (element == null) 438 { 439 throw new InvalidOperationException("Can't hook to events other than UI Element"); 440 } 441 442 if (e.NewValue != null) 443 { 444 RichToolTip popup = e.NewValue as RichToolTip; 445 446 if (popup != null) 447 { 448 popup.Load(element); 449 } 450 else 451 { 452 popup = new RichToolTip(element); 453 454 Binding binding = new Binding 455 { 456 Path = new PropertyPath(PopupContentProperty), 457 Mode = BindingMode.OneWay, 458 Source = o, 459 }; 460 popup.SetBinding(ContentProperty, binding); 461 } 462 463 SetContentTooltipWrapper(o, popup); 464 } 465 } 466 #endregion 467 468 #region ContentTooltipWrapper 469 internal static RichToolTip GetContentTooltipWrapper(DependencyObject obj) 470 { 471 return (RichToolTip)obj.GetValue(ContentTooltipWrapperProperty); 472 } 473 474 internal static void SetContentTooltipWrapper(DependencyObject obj, RichToolTip value) 475 { 476 obj.SetValue(ContentTooltipWrapperProperty, value); 477 } 478 479 internal static readonly DependencyProperty ContentTooltipWrapperProperty = 480 DependencyProperty.RegisterAttached("ContentTooltipWrapper", typeof(RichToolTip), typeof(RichToolTip)); 481 #endregion 482 483 #endregion 484 485 #region Root Visual Binding 486 bool _boundToRoot = false; 487 bool _hasParentWindow = false; 488 Window _parentWindow = null; 489 490 void BindRootVisual() 491 { 492 if (!_boundToRoot) 493 { 494 if (!BrowserInteropHelper.IsBrowserHosted) 495 { 496 _parentWindow = UIHelpers.FindLogicalAncestorByType<Window>(_relatedObject) 497 ?? UIHelpers.FindVisualAncestorByType<Window>(_relatedObject); 498 499 if (_parentWindow != null) 500 { 501 _hasParentWindow = true; 502 503 _parentWindow.Deactivated += window_Deactivated; 504 _parentWindow.LocationChanged += window_LocationChanged; 505 } 506 } 507 508 _boundToRoot = true; 509 } 510 } 511 512 void UnbindRootVisual() 513 { 514 if (_boundToRoot) 515 { 516 if (_parentWindow != null) 517 { 518 _parentWindow.Deactivated -= window_Deactivated; 519 _parentWindow.LocationChanged -= window_LocationChanged; 520 } 521 522 _boundToRoot = false; 523 } 524 } 525 #endregion 526 527 #region Animations & Intervals 528 static DispatcherTimer _timer; 529 static Storyboard _showStoryboard; 530 static Storyboard _hideStoryboard; 531 bool setRenderTransform; 532 533 static void InitStoryboards() 534 { 535 _showStoryboard = new Storyboard(); 536 _hideStoryboard = new Storyboard(); 537 538 TimeSpan duration = TimeSpan.FromMilliseconds(_animationDurationInMs); 539 540 DoubleAnimation animation = new DoubleAnimation(1, duration, FillBehavior.Stop); 541 Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty)); 542 _showStoryboard.Children.Add(animation); 543 544 animation = new DoubleAnimation(0.1, 1, duration, FillBehavior.Stop); 545 Storyboard.SetTargetProperty(animation, new PropertyPath("(0).(1)", FrameworkElement.RenderTransformProperty, ScaleTransform.ScaleXProperty)); 546 _showStoryboard.Children.Add(animation); 547 548 animation = new DoubleAnimation(0.1, 1, duration, FillBehavior.Stop); 549 Storyboard.SetTargetProperty(animation, new PropertyPath("(0).(1)", FrameworkElement.RenderTransformProperty, ScaleTransform.ScaleYProperty)); 550 _showStoryboard.Children.Add(animation); 551 552 animation = new DoubleAnimation(0, duration, FillBehavior.Stop); 553 Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty)); 554 _hideStoryboard.Children.Add(animation); 555 556 _hideStoryboard.Completed += delegate { OnAnimationCompleted(); }; 557 } 558 559 static void InitTimer() 560 { 561 _timer = new DispatcherTimer(); 562 _timer.Interval = TimeSpan.FromMilliseconds(_showDeferredMilliseconds); 563 } 564 565 static void ResetTimer(RichToolTip tooltip) 566 { 567 if (_timer != null) 568 { 569 _timer.Tick -= tooltip.ShowDeferred; 570 _timer.Stop(); 571 } 572 } 573 574 void Animate(bool show) 575 { 576 if (show) 577 { 578 if (!setRenderTransform) 579 { 580 RenderTransform = new ScaleTransform(); 581 582 setRenderTransform = true; 583 } 584 585 _showStoryboard.Begin(this); 586 } 587 else 588 { 589 _hideStoryboard.Begin(this); 590 } 591 } 592 593 static void OnAnimationCompleted() 594 { 595 HideLastShown(false); 596 } 597 #endregion 598 599 #region Event Invocations 600 void element_MouseEnter(object sender, MouseEventArgs e) 601 { 602 if (!IsShown() && this != _lastShownPopup) 603 { 604 if (!_hasParentWindow || _parentWindow.IsActive) 605 { 606 Show(true); 607 } 608 } 609 } 610 611 void element_MouseLeave(object sender, MouseEventArgs e) 612 { 613 ResetTimer(this); 614 615 if (IsShown() && this == _lastShownPopup) 616 { 617 Hide(true); 618 } 619 } 620 621 static void OnNavigationWindowMouseLeaveEvent(object sender, RoutedEventArgs e) 622 { 623 Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, 624 new Action(() => 625 { 626 if (_lastShownPopup != null && !_lastShownPopup.IsMouseOver) 627 { 628 HideLastShown(false); 629 } 630 })); 631 } 632 633 void window_LocationChanged(object sender, EventArgs e) 634 { 635 if (IsShown()) 636 { 637 HideLastShown(false); 638 } 639 } 640 641 void window_Deactivated(object sender, EventArgs e) 642 { 643 if (IsShown()) 644 { 645 HideLastShown(false); 646 } 647 } 648 649 static void OnWindowSizeChanged(object sender, RoutedEventArgs e) 650 { 651 HideLastShown(); 652 } 653 654 static void OnElementMouseDown(object sender, MouseButtonEventArgs e) 655 { 656 if (_lastShownPopup != null && _lastShownPopup.IsShown()) 657 { 658 RichToolTip popup; 659 660 DependencyObject o = e.OriginalSource as DependencyObject; 661 if (!TryFindPopupParent(e.OriginalSource, out popup)) 662 { 663 HideLastShown(true); 664 } 665 } 666 } 667 668 static void OnButtonBaseClick(object sender, RoutedEventArgs e) 669 { 670 if (_lastShownPopup != null && _lastShownPopup.IsShown()) 671 { 672 DependencyObject o = e.OriginalSource as DependencyObject; 673 674 bool hide = GetHideOnClick(o); 675 if (hide) 676 { 677 HideLastShown(true); 678 679 e.Handled = true; 680 } 681 } 682 } 683 684 static void selector_SelectionChangedEvent(object sender, SelectionChangedEventArgs e) 685 { 686 HideLastShown(); 687 } 688 689 static bool TryFindPopupParent(object source, out RichToolTip popup) 690 { 691 popup = null; 692 UIElement element = source as UIElement; 693 694 if (element != null) 695 { 696 popup = UIHelpers.FindVisualAncestorByType<RichToolTip>(element); 697 698 if (popup == null) 699 { 700 popup = UIHelpers.FindLogicalAncestorByType<RichToolTip>(element); 701 } 702 703 return popup != null; 704 } 705 706 return false; 707 } 708 #endregion 709 710 #region Show / Hide 711 bool _showAnimate = _animationEnabledDefault; 712 713 bool IsShown() 714 { 715 return IsOpen; 716 } 717 718 public void Show(bool animate) 719 { 720 _showAnimate = animate; 721 722 if (_timer == null) 723 { 724 InitTimer(); 725 } 726 727 _timer.Tick += ShowDeferred; 728 729 if (!_timer.IsEnabled) 730 { 731 _timer.Start(); 732 } 733 } 734 735 private void ShowDeferred(object sender, EventArgs e) 736 { 737 ResetTimer(this); 738 739 HideLastShown(false); 740 741 ShowInternal(); 742 743 if (_showAnimate && EnableAnimation) 744 { 745 Animate(true); 746 } 747 else 748 { 749 this.Opacity = 1; 750 } 751 752 _lastShownPopup = this; 753 } 754 755 private void ShowInternal() 756 { 757 Visibility = Visibility.Visible; 758 759 IsOpen = true; 760 } 761 762 static void HideLastShown() 763 { 764 HideLastShown(false); 765 } 766 767 static void HideLastShown(bool animate) 768 { 769 if (_lastShownPopup != null) 770 { 771 _lastShownPopup.Hide(animate); 772 } 773 } 774 775 /// <summary> 776 /// 777 /// </summary> 778 /// <param name="animate"></param> 779 public void Hide(bool animate) 780 { 781 Point pt = Mouse.GetPosition(this); 782 if (pt.X >= 0 && pt.Y >= 0 && pt.X <= this.ActualWidth && pt.Y <= this.ActualHeight) return; 783 784 if (animate && EnableAnimation) 785 { 786 Animate(false); 787 } 788 else 789 { 790 HideInternal(); 791 } 792 } 793 794 private void HideInternal() 795 { 796 this.Visibility = Visibility.Collapsed; 797 this.IsOpen = false; 798 799 _lastShownPopup = null; 800 } 801 802 #endregion 803 } 804 }