diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/Given_HyperlinkButton.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/Given_HyperlinkButton.cs new file mode 100644 index 000000000000..4c8e023e5cc5 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/Given_HyperlinkButton.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Private.Infrastructure; +using Windows.UI.Text; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls.HyperlinkButtonTests +{ + [TestClass] + public class Given_HyperlinkButton + { + [TestMethod] + [RunsOnUIThread] + public async Task When_HyperlinkButton_With_Implicit_Content_Should_Be_UnderlinedAsync() + { + var SUT = new HyperlinkButtonPage(); + TestServices.WindowHelper.WindowContent = SUT; + await TestServices.WindowHelper.WaitForIdle(); + + var underlinedImplicitTextBlock = VisualTreeHelper.GetChild(SUT.ShouldBeUnderlinedHyperlinkButton.GetTemplateChild("ContentPresenter"), 0) as TextBlock; + Assert.IsInstanceOfType(underlinedImplicitTextBlock, typeof(ImplicitTextBlock)); + Assert.AreEqual(TextDecorations.Underline, underlinedImplicitTextBlock.TextDecorations); + + var notUnderlinedTextBlock = VisualTreeHelper.GetChild(SUT.ShouldNotBeUnderlinedHyperlinkButton.GetTemplateChild("ContentPresenter"), 0) as TextBlock; + Assert.IsNotInstanceOfType(notUnderlinedTextBlock, typeof(ImplicitTextBlock)); + Assert.AreEqual(TextDecorations.None, notUnderlinedTextBlock.TextDecorations); + } + } +} diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/HyperlinkButtonPage.xaml b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/HyperlinkButtonPage.xaml new file mode 100644 index 000000000000..f44ff3b14754 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/HyperlinkButtonPage.xaml @@ -0,0 +1,17 @@ + + + + Should be underlined text + + Shouldn't be underlined text + + + diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/HyperlinkButtonPage.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/HyperlinkButtonPage.xaml.cs new file mode 100644 index 000000000000..38982bc121a0 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/HyperlinkButtonTests/HyperlinkButtonPage.xaml.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls.HyperlinkButtonTests +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class HyperlinkButtonPage : Page + { + public HyperlinkButton ShouldBeUnderlinedHyperlinkButton => ShouldBeUnderlined_HyperlinkButton; + public HyperlinkButton ShouldNotBeUnderlinedHyperlinkButton => ShouldNotBeUnderlined_HyperlinkButton; + public TextBlock ShouldNotBeUnderlinedTextBlock => ShouldNotBeUnderlined_TextBlock; + + public HyperlinkButtonPage() + { + this.InitializeComponent(); + } + } +} diff --git a/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.csproj b/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.csproj index f01beed1a1bf..7aebf99eac8f 100644 --- a/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.csproj +++ b/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.csproj @@ -112,6 +112,14 @@ + + + + + + + + diff --git a/src/Uno.UI/UI/Xaml/Controls/Button/HyperlinkButton.cs b/src/Uno.UI/UI/Xaml/Controls/Button/HyperlinkButton.cs index 32b72ce0f711..7c4fa6dac48c 100644 --- a/src/Uno.UI/UI/Xaml/Controls/Button/HyperlinkButton.cs +++ b/src/Uno.UI/UI/Xaml/Controls/Button/HyperlinkButton.cs @@ -19,9 +19,26 @@ public HyperlinkButton() DefaultStyleKey = typeof(HyperlinkButton); } - /// - /// Gets or sets the Uniform Resource Identifier (URI) to navigate to when the HyperlinkButton is clicked. - /// + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + // This differs from UWP, where it looks for a template child named "ContentPresenter", + // but ultimately sets the underline on the TextBlock of the first ContentPresenter with a {TemplateBinding Content}. + // UWP also doesn't seem to do this in OnApplyTemplate (it's done between the first Measure and the first Arrange). + if (GetTemplateChild("ContentPresenter") is ContentPresenter contentPresenter) + { + // Forces ContentPresenter to materialize its template. + contentPresenter.Measure(new Size(0, 0)); + if (VisualTreeHelper.GetChildrenCount(contentPresenter) == 1 && VisualTreeHelper.GetChild(contentPresenter, 0) is ImplicitTextBlock textBlock) + { + textBlock.TextDecorations = Windows.UI.Text.TextDecorations.Underline; + } + } + } + + #region NavigateUri + public Uri NavigateUri { get => (Uri)GetValue(NavigateUriProperty);