2011-03-03 18 views
7

我嘗試在Hyperlink上使用Style對象設置Foreground顏色,但其沒有任何效果。我甚至使用Changing Hyperlink foreground without losing hover colorBasedOn提示,但它沒有什麼區別 - 我仍然會看到一個藍色超鏈接,它在懸停時顯示爲紅色。如何將樣式傳播到DataTemplate中的超鏈接?

下面是我的控制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> 

這是值得注意的是,我不想直接在DataTemplateHyperlink上設置不同的顏色。這是因爲模板將被使用不同的ItemsControl對象,其中大多數對象將在白色背景上,因此可以使用標準的超鏈接顏色。 (注意,上面的XAML中的那個背景是紅色的。)

總之,我不希望DataTemplate必須知道任何有關使用它的控件。模板控件的樣式應該過濾到它。

所以......任何人都可以告訴我爲什麼風格沒有過濾掉,我能做些什麼來解決它?

謝謝。

更新:
因爲我不能讓帕夫洛的答案在我的生產應用程序的工作,因爲我已經嘗試過在一個單獨的測試程序。該應用程序是一個WinForms應用程序,主窗體僅包含一個ElementHost,它本身包含一個簡單的WPF用戶控件。下面是它的XAML:「只能與目標類型風格是基本類型‘IFrameworkInputElement’基地」

<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,說明

可以通過將TargetType="Hyperlink"置於UserControl.Resources元素內的Style定義上來修復這個問題。然而,當正在顯示的信息,他們的鏈接部分仍然有默認的藍色超鏈接樣式:

Blue hyperlinks persist

總之,它不工作,所以我歡迎任何其他建議/更正。 :(

更新2:
感謝來自帕夫洛替代的解決方案,現在工作:)

回答

7

經過一番google搜索我碰到了這個帖子: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屬性。

但是,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將所有鏈接黃色/白色,而在外面,他們將是藍色的。

希望這會有所幫助。

+0

令人敬畏的谷歌搜索技巧 - 謝謝!還有一個非常完整的答案。我會試試這個,並將其標記爲接受後,我有它的工作。 – 2011-03-03 17:47:30

+0

忘記我的應用程序是使用'ElementHost'的WinForms應用程序,所以我沒有app.xaml文件。儘管如此,原理看起來很合理,所以我試着在我的UserControl資源字典中的DataTemplate之前添加一個空的MyDefaultHyperlinkStyle,並留下上面看到的特定的StackPanel以用它自己的定義替換它。可悲的是,它仍然無法正常工作。我會繼續嘗試...... – 2011-03-03 21:20:19

+0

@Mal - 你忘了在數據模板本身中包括樣式:'