Browse Source

Merge pull request #4407 from AvaloniaUI/fixes/tooltip-stuck-on-screen

Fixes/tooltip stuck on screen
danwalmsley 5 years ago
parent
commit
06b9c3b77b

+ 1 - 0
src/Avalonia.Controls/ToolTip.cs

@@ -66,6 +66,7 @@ namespace Avalonia.Controls
         static ToolTip()
         {
             TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
+            IsOpenProperty.Changed.Subscribe(ToolTipService.Instance.TipOpenChanged);
             IsOpenProperty.Changed.Subscribe(IsOpenChanged);
         }
 

+ 14 - 1
src/Avalonia.Controls/ToolTipService.cs

@@ -28,20 +28,33 @@ namespace Avalonia.Controls
             {
                 control.PointerEnter -= ControlPointerEnter;
                 control.PointerLeave -= ControlPointerLeave;
-                control.DetachedFromVisualTree -= ControlDetaching;
             }
 
             if (e.NewValue != null)
             {
                 control.PointerEnter += ControlPointerEnter;
                 control.PointerLeave += ControlPointerLeave;
+            }
+        }
+
+        internal void TipOpenChanged(AvaloniaPropertyChangedEventArgs e)
+        {
+            var control = (Control)e.Sender;
+
+            if (e.OldValue is false && e.NewValue is true)
+            {
                 control.DetachedFromVisualTree += ControlDetaching;
             }
+            else if(e.OldValue is true && e.NewValue is false)
+            {
+                control.DetachedFromVisualTree -= ControlDetaching;
+            }
         }
         
         private void ControlDetaching(object sender, VisualTreeAttachmentEventArgs e)
         {
             var control = (Control)sender;
+            control.DetachedFromVisualTree -= ControlDetaching;
             Close(control);
         }
 

+ 39 - 0
tests/Avalonia.Controls.UnitTests/ToolTipTests.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Reactive.Disposables;
+using Avalonia.Markup.Xaml;
 using Avalonia.Platform;
 using Avalonia.Threading;
 using Avalonia.UnitTests;
@@ -64,6 +65,39 @@ namespace Avalonia.Controls.UnitTests
                 Assert.False(ToolTip.GetIsOpen(target));
             }
         }
+        
+        [Fact]
+        public void Should_Close_When_Tip_Is_Opened_And_Detached_From_Visual_Tree()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
+    <Panel x:Name='PART_panel'>
+        <Decorator x:Name='PART_target' ToolTip.Tip='{Binding Tip}' ToolTip.ShowDelay='0' />
+    </Panel>
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                
+                window.DataContext = new ToolTipViewModel();
+                window.ApplyTemplate();
+                window.Presenter.ApplyTemplate();
+
+                var target = window.Find<Decorator>("PART_target");
+                var panel = window.Find<Panel>("PART_panel");
+                
+                Assert.True((target as IVisual).IsAttachedToVisualTree);                               
+
+                _mouseHelper.Enter(target);
+
+                Assert.True(ToolTip.GetIsOpen(target));
+
+                panel.Children.Remove(target);
+                
+                Assert.False(ToolTip.GetIsOpen(target));
+            }
+        }
 
         [Fact]
         public void Should_Open_On_Pointer_Enter()
@@ -208,4 +242,9 @@ namespace Avalonia.Controls.UnitTests
             }
         }
     }
+
+    internal class ToolTipViewModel
+    {
+        public string Tip => "Tip";
+    }
 }