gpt4 book ai didi

wpf - 如何将样式传播到 DataTemplate 内的超链接?

转载 作者:行者123 更新时间:2023-12-04 12:00:08 25 4
gpt4 key购买 nike

我正在尝试设置 Foreground Hyperlink 上的颜色使用 Style祖先的对象 Resources ,但它没有任何影响。我什至使用了 BasedOn来自 Changing Hyperlink foreground without losing hover color 的提示,但它没有任何区别 - 我仍然得到一个蓝色超链接,悬停时为红色。

这是我的控件的 XAML,包括 ItemsControl其项目使用超链接显示:

<StackPanel Background="Red" TextElement.Foreground="White">
<StackPanel.Resources>
<Style TargetType="Hyperlink" BasedOn="{StaticResource {x:Type Hyperlink}}">
<Setter Property="Foreground" Value="Yellow"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBlock>Data import errors</TextBlock>
<ItemsControl ItemsSource="{Binding Errors}"/>
</StackPanel>

以及 ItemsControl 中的项目正在接以下 DataTemplate :
<DataTemplate DataType="{x:Type Importer:ConversionDetailsMessage}">
<TextBlock>
<Run Text="{Binding Message, Mode=OneTime}"/>
<Hyperlink Command="Common:ImportDataCommands.ExplainConversionMessage" CommandParameter="{Binding}">
<Run Text="{Binding HelpLink.Item2, Mode=OneTime}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>

同样值得注意的是,我不想直接在 Hyperlink 上设置不同的颜色。在 DataTemplate .这是因为模板会被多个不同的 ItemsControl 使用对象,其中大部分将在白色背景上,因此可以使用标准的超链接颜色。 (但是请注意,上面 XAML 中的那个背景是红色的。)

简而言之,我不想要 DataTemplate必须了解有关使用它的控件的任何信息。模板控件的样式应该只是过滤到它。

所以......谁能告诉我为什么样式没有过滤掉以及我可以做些什么来修复它?

谢谢。

更新:
由于我无法在我的生产应用程序中获得 Pavlo 的答案,因此我在单独的测试应用程序中尝试了它。该应用程序是一个 WinForms 应用程序,主窗体只包含一个 ElementHost ,它本身包含一个简单的 WPF 用户控件。这是它的 XAML:
<UserControl x:Class="DataTemplateStyling.StylingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:DataTemplateStyling="clr-namespace:DataTemplateStyling"
x:Name="root" Loaded="StylingViewLoaded">

<UserControl.Resources>
<Style x:Key="MyDefaultHyperlinkStyle" BasedOn="{StaticResource {x:Type Hyperlink}}"/>

<DataTemplate DataType="{x:Type DataTemplateStyling:ImportMessage}">
<DataTemplate.Resources>
<Style TargetType="{x:Type Hyperlink}"
BasedOn="{StaticResource MyDefaultHyperlinkStyle}"/>
</DataTemplate.Resources>
<TextBlock>
<Run Text="{Binding Message, Mode=OneTime}"/>
<Hyperlink NavigateUri="{Binding HelpLink.Item1}">
<Run Text="{Binding HelpLink.Item2, Mode=OneTime}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</UserControl.Resources>

<Grid DataContext="{Binding ElementName=root}">
<StackPanel Background="Red" TextElement.Foreground="White">
<StackPanel.Resources>
<Style x:Key="MyDefaultHyperlinkStyle" TargetType="Hyperlink" BasedOn="{StaticResource {x:Type Hyperlink}}">
<Setter Property="Foreground" Value="Yellow"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBlock>Data import errors</TextBlock>
<ItemsControl ItemsSource="{Binding Messages}"/>
</StackPanel>
</Grid>
</UserControl>

如上所示,这会生成 InvalidOperationException ,说明“只能基于目标类型为‘IFrameworkInputElement’的样式。”

这可以通过放置 TargetType="Hyperlink" 来解决在 Style立即在 UserControl.Resources 内定义元素。但是,在显示消息时,它们的链接部分仍然具有默认的蓝色超链接样式:

Blue hyperlinks persist

简而言之,它不起作用,所以我欢迎任何其他建议/更正。 :(

更新 2:
多亏了 Pavlo 的替代解决方案,现在 在职的。 :)

最佳答案

经过一番谷歌搜索后,我遇到了这个帖子:http://www.11011.net/archives/000692.html .

正如那里描述的那样,事实证明不是从 Control 派生的元素。 (如 TextBlockHyperlink )不要在 DataTemplate 之外寻找隐式样式边界。

同样,正如文章所说,可能的解决方法是明确指定样式键。在你的情况下,它可能是这样的:

<StackPanel Background="Red" TextElement.Foreground="White">
<StackPanel.Resources>
<Style x:Key="MyDefaultHyperlinkStyle" TargetType="Hyperlink" BasedOn="{StaticResource {x:Type Hyperlink}}">
<Setter Property="Foreground" Value="Yellow"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBlock>Data import errors</TextBlock>
<ItemsControl ItemsSource="{Binding Errors}"/>
</StackPanel>

然后,您可以为 Hyperlink 添加隐式样式仅引用我们在 DataTemplate 中命名的样式资源:
<DataTemplate DataType="{x:Type Importer:ConversionDetailsMessage}">
<DataTemplate.Resources>
<Style TargetType="{x:Type Hyperlink}"
BasedOn="{StaticResource MyDefaultHyperlinkStyle}"/>
</DataTemplate.Resources>
<TextBlock>
<Run Text="{Binding Message, Mode=OneTime}"/>
<Hyperlink Command="Common:ImportDataCommands.ExplainConversionMessage" CommandParameter="{Binding}">
<Run Text="{Binding HelpLink.Item2, Mode=OneTime}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>

并且因为数据模板可以在不同的地方使用,所以有可能父容器没有定义键为“MyDefaultHyperlinkStyle”的样式。在这种情况下,将抛出一个异常,表示找不到资源“MyDefaultHyperlinkStyle”。为了解决这个问题,您可以使用这样的键定义一个样式,该样式只会继承 App.xaml 中某处的默认样式:
<Style x:Key="MyDefaultHyperlinkStyle"
BasedOn="{StaticResource {x:Type Hyperlink}}/>

更新:

由于静态资源的性质,您更新中包含的代码将不起作用,这意味着日期模板中的以下资源引用...
BasedOn="{StaticResource MyDefaultHyperlinkStyle}"

...将始终指向以下资源(这是默认样式):
<Style x:Key="MyDefaultHyperlinkStyle" BasedOn="{StaticResource {x:Type Hyperlink}}"/>

静态资源引用在编译时解析,因此使用树中最近的资源。

您可能会想使用 DynamicResource ,但不幸的是它不支持 BasedOn属性(property)。

但是, Foreground属性支持动态资源,因此我们可以对我们在样式中使用的画笔使用相同的技巧。这是您的测试用户控件修改为使用动态画笔:
<UserControl x:Class="DataTemplateStyling.StylingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:DataTemplateStyling="clr-namespace:DataTemplateStyling"
x:Name="root"
Loaded="StylingViewLoaded">

<UserControl.Resources>
<SolidColorBrush x:Key="HyperlinkForeground"
Color="Blue" />

<SolidColorBrush x:Key="HyperlinkHoverForeground"
Color="Gray" />

<Style x:Key="MyDefaultHyperlinkStyle"
TargetType="Hyperlink"
BasedOn="{StaticResource {x:Type Hyperlink}}">
<Setter Property="Foreground"
Value="{DynamicResource HyperlinkForeground}" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource HyperlinkHoverForeground}" />
</Trigger>
</Style.Triggers>
</Style>

<DataTemplate DataType="{x:Type DataTemplateStyling:ImportMessage}">
<DataTemplate.Resources>
<Style TargetType="{x:Type Hyperlink}"
BasedOn="{StaticResource MyDefaultHyperlinkStyle}" />
</DataTemplate.Resources>
<TextBlock>
<Run Text="{Binding Message, Mode=OneTime}" />
<Hyperlink NavigateUri="{Binding HelpLink.Item1}">
<Run Text="{Binding HelpLink.Item2, Mode=OneTime}" />
</Hyperlink>
</TextBlock>
</DataTemplate>
</UserControl.Resources>

<Grid DataContext="{Binding ElementName=root}">
<StackPanel Background="Red"
TextElement.Foreground="White">
<StackPanel.Resources>
<SolidColorBrush x:Key="HyperlinkForeground"
Color="Yellow" />

<SolidColorBrush x:Key="HyperlinkHoverForeground"
Color="White" />
</StackPanel.Resources>
<TextBlock>Data import errors</TextBlock>
<ItemsControl ItemsSource="{Binding Messages}" />
</StackPanel>
</Grid>
</UserControl>

它按预期工作,即 StackPanel 中的所有链接将是黄色/白色,而在外面它们将是蓝色。

希望这可以帮助。

关于wpf - 如何将样式传播到 DataTemplate 内的超链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5182135/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com