WPF的悬停工具栏实现方案

解决方法:参照ToolTip控件实现一个功能更为强大的ToolTip(命名为RichToolTip)

1、目标:仿照Word2007的悬停工具栏,如下图实现上下文工具栏。
WPF的悬停工具栏实现方案
WPF的悬停工具栏实现方案

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、代码实现:

RichToolTip Control's Code
  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 }

 

你可能感兴趣的:(WPF)