UWP:如何使用TextBox控件创建自定义超链接控件



我想给我的UWP应用程序添加一个超链接,看起来像这个

<Grid
Background="Gray">
<TextBlock>
<Hyperlink
Foreground="Red"
NavigateUri="https://randomWebsiteLink">Click here</Hyperlink>
</TextBlock>
</Grid>

这在浅色模式下工作得很好,但当我将主题更改为深色,悬停在超链接上时;点击这里";在与栅格背景混合时变得不可见。我试着在悬停时更改颜色,但我看到了这篇文章"更改超链接的悬停颜色",建议不要这样做。我现在正试图使用文本框创建一个自定义超链接

<Grid
Background="Gray">
<TextBlock
Text="Click here"
TextDecorations="Underline"
Foreground="Gray">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction  Command="{x:Bind ViewModel.OnLinkClicked}"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBlock>
</Grid>

当我点击文本";单击此处";我确实看到浏览器中打开了链接。然而,我想通过操纵视觉状态来完全模拟超链接控件。我希望在悬停或按下时更改文本的前景色。我正在考虑使用视觉状态。这是个好主意吗?我该怎么做?

如果您想在悬停或按下时更改文本的颜色,则需要创建TextBox的自定义样式。

首先,单击Visual Studio中的"文档大纲"窗口,然后在可视化树中找到目标TextBox。然后右键单击TextBox并将鼠标移动到所选内容-Edit Template。会有一个弹出窗口,您可以选择Edit a Copy。之后,您将看到一个默认的TextBox样式被添加到XAML资源中。

现在您获得了默认样式,下一步是更改TextBox的默认行为。默认样式中有许多视觉状态组,请确保更改了正确的状态组。第一个视觉状态组属于TextBox的删除按钮,跳过它。转到第二个视觉状态分组,找到名为PointerOverVisualState,你会看到一个针对ContentElement's foreground属性的动画。这是您要查找的位置,请将值更改为要使用的颜色。

代码如下:

<Style x:Key="TextBoxStyle1" TargetType="TextBox">
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}"/>
<Setter Property="Background" Value="{ThemeResource TextControlBackground}"/>
..... some properties
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.Resources>
<Style x:Name="DeleteButtonStyle" TargetType="Button">
...some styles...
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
...some animations...
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource Mode=TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundPointerOver}}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
...some animations...
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
...some animations...
</VisualState>
<VisualState x:Name="ButtonCollapsed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.ColumnSpan="2" Grid.Column="0" FontWeight="Normal" Foreground="{ThemeResource TextControlHeaderForeground}" Margin="{ThemeResource TextBoxTopHeaderMargin}" Grid.Row="0" TextWrapping="Wrap" VerticalAlignment="Top" Visibility="Collapsed" x:DeferLoadStrategy="Lazy"/>
<Border x:Name="BorderElement" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="{TemplateBinding CornerRadius}" Grid.ColumnSpan="2" Grid.Column="0" Control.IsTemplateFocusTarget="True" MinHeight="{ThemeResource TextControlThemeMinHeight}" MinWidth="{ThemeResource TextControlThemeMinWidth}" Grid.RowSpan="1" Grid.Row="1"/>
<ScrollViewer x:Name="ContentElement" AutomationProperties.AccessibilityView="Raw" Grid.Column="0" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsTabStop="False" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" ZoomMode="Disabled"/>
<TextBlock x:Name="PlaceholderTextContentPresenter" Grid.ColumnSpan="2" Grid.Column="0" Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource Mode=TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}" IsHitTestVisible="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" Text="{TemplateBinding PlaceholderText}" TextWrapping="{TemplateBinding TextWrapping}" TextAlignment="{TemplateBinding TextAlignment}"/>
<Button x:Name="DeleteButton" AutomationProperties.AccessibilityView="Raw" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1" FontSize="{TemplateBinding FontSize}" IsTabStop="False" MinWidth="34" Margin="{ThemeResource HelperButtonThemePadding}" Grid.Row="1" Style="{StaticResource DeleteButtonStyle}" VerticalAlignment="Stretch" Visibility="Collapsed"/>
<ContentPresenter x:Name="DescriptionPresenter" AutomationProperties.AccessibilityView="Raw" Content="{TemplateBinding Description}" Grid.ColumnSpan="2" Grid.Column="0" Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}" Grid.Row="2" x:Load="False"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

有关更多信息,请参阅文档:教程:创建自定义样式

更新:

如果您现在使用的是TextBlock而不是TextBox,那么您可以尝试另一种简单的方法。

您可以尝试遵循以下代码:

在您的Xaml:中

<Grid>
<TextBlock x:Name="MyTextBlock" Foreground="Aqua" Height="100" Text="This is a test Text" PointerEntered="MyTextBlock_PointerEntered" PointerExited="MyTextBlock_PointerExited" />

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="TextBlockStates">
<VisualState x:Name="Nor"/>
<VisualState x:Name="PointOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MyTextBlock" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>

在后面的代码中:

private void MyTextBlock_PointerExited(object sender, PointerRoutedEventArgs e)
{
VisualStateManager.GoToState(this, "Nor", true);
}
private void MyTextBlock_PointerEntered(object sender, PointerRoutedEventArgs e)
{

VisualStateManager.GoToState(this, "PointOver", true);
}

最新更新