2011-03-03 24 views
7

Tôi đang cố gắng đặt màu Foreground trên Hyperlink bằng cách sử dụng đối tượng Style trong tổ tiên của Resources, nhưng nó không có hiệu lực. Tôi thậm chí còn sử dụng mẹo BasedOn từ Changing Hyperlink foreground without losing hover color, nhưng nó không tạo ra bất kỳ sự khác biệt nào - tôi vẫn nhận được một siêu liên kết màu xanh dương có màu đỏ khi di chuột.Làm thế nào để truyền bá phong cách cho các siêu liên kết bên trong một DataTemplate?

Đây là XAML cho các điều khiển của tôi, trong đó có một ItemsControl mà mục được hiển thị bằng một siêu liên kết:

<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> 

Và các mục trong ItemsControl đang nhặt sau 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> 

Đó là đáng chú ý, quá, mà tôi không muốn chỉ thiết lập các màu sắc khác nhau trực tiếp trên Hyperlink trong DataTemplate. Điều này là do mẫu sẽ được sử dụng bởi một số của các đối tượng khác nhau ItemsControl, hầu hết trong số đó sẽ có nền màu trắng và do đó có thể sử dụng các màu siêu liên kết chuẩn. (Lưu ý rằng cái trong XAML ở trên, tuy nhiên, có nền màu đỏ.)

Tóm lại, tôi không muốn DataTemplate phải biết bất kỳ điều gì về điều khiển mà nó đang được sử dụng. Các kiểu cho các điều khiển của mẫu sẽ chỉ lọc xuống.

Vì vậy, ... bất kỳ ai cũng có thể cho tôi biết tại sao kiểu không lọc xuống và tôi có thể làm gì để khắc phục?

Cảm ơn.

Cập nhật:
Vì tôi không thể có được câu trả lời Pavlo để làm việc trong ứng dụng sản xuất của tôi, tôi đã kể từ khi thử nó trong một ứng dụng thử nghiệm riêng biệt. Ứng dụng này là một ứng dụng WinForms, với biểu mẫu chính không chứa gì ngoài một số ElementHost, bản thân nó chứa một người dùng WPF đơn giản. Dưới đây là XAML của nó: "Có thể chỉ dựa vào một phong cách với loại mục tiêu đó là kiểu cơ sở '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> 

Khi đứng trên, điều này tạo ra một InvalidOperationException, trong đó nêu

Điều đó có thể được sửa bằng cách đặt TargetType="Hyperlink" trên định nghĩa Style ngay bên trong phần tử UserControl.Resources. Tuy nhiên, trong khi các thông điệp đang được hiển thị, phần liên kết trong số họ vẫn có phong cách siêu liên kết màu xanh mặc định:

Blue hyperlinks persist

Nói tóm lại, nó không làm việc, vì vậy tôi muốn hoan nghênh bất kỳ lời đề nghị khác/sửa chữa. :(

Cập nhật 2:
Nhờ một giải pháp thay thế từ Pavlo, nó bây giờ làm việc :)

Trả lời

7

Sau khi một số googling tôi chạy vào bài đăng này:. http://www.11011.net/archives/000692.html.

Như được mô tả ở đó, nó chỉ ra rằng các phần tử không bắt nguồn từ Control (như TextBlockHyperlink) không tìm kiếm các kiểu ẩn bên ngoài ranh giới DataTemplate.

Một lần nữa, như bài báo nói rằng, các cách giải quyết có thể là chỉ định phím phong cách rõ ràng. Trong trường hợp của bạn nó có thể là một cái gì đó như thế này:

<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> 

Sau đó, bạn có thể thêm một phong cách ngầm cho Hyperlink mà chỉ tham chiếu phong cách đặt tên của chúng tôi trong DataTemplate nguồn:

<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> 

Và bởi vì các mẫu dữ liệu có thể được sử dụng ở những nơi khác nhau, có khả năng là vùng chứa mẹ không xác định kiểu có khóa "MyDefaultHyperlinkStyle". Trong trường hợp này, một ngoại lệ sẽ được ném ra rằng không thể tìm thấy tài nguyên "MyDefaultHyperlinkStyle". Để giải quyết điều này, bạn có thể xác định một phong cách với trọng như vậy sẽ chỉ kế thừa phong cách mặc định ở đâu đó trong App.xaml:

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

Cập nhật:

Mã bạn đã bao gồm trong bản cập nhật của bạn sẽ không hoạt động vì về bản chất của các tài nguyên tĩnh, có nghĩa là tài liệu tham khảo tài nguyên sau trong ngày mẫu ...

BasedOn="{StaticResource MyDefaultHyperlinkStyle}" 

... sẽ luôn trỏ đến tài nguyên sau (đó là phong cách mặc định):

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

Tài nguyên tĩnh được giải quyết tại thời gian biên dịch, do đó tài nguyên gần nhất trong cây được sử dụng.

Bạn có thể bị cám dỗ sử dụng DynamicResource, nhưng tiếc là nó không được hỗ trợ với thuộc tính BasedOn.

NHƯNG, Foreground tài sản hỗ trợ nguồn lực năng động, vì vậy chúng tôi có thể sử dụng các thủ thuật tương tự với bàn chải chúng tôi sử dụng trong phong cách của chúng tôi. Đây là điều khiển người dùng thử nghiệm của bạn sửa đổi để sử dụng bàn chải động:

<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> 

Nó hoạt động như mong đợi, ví dụ: tất cả các liên kết bên trong StackPanel sẽ vàng/trắng, trong khi bên ngoài họ sẽ có màu xanh.

Hy vọng điều này sẽ hữu ích.

+0

Kỹ năng googling tuyệt vời - cảm ơn! Và một câu trả lời rất hoàn chỉnh. Tôi sẽ thử điều này và đánh dấu nó như được chấp nhận khi tôi đã làm việc. –

+0

Quên ứng dụng của tôi là một ứng dụng WinForms sử dụng 'ElementHost', vì vậy tôi không có tệp app.xaml. Tuy nhiên, nguyên tắc có vẻ như âm thanh, vì vậy tôi đã thử thêm 'MyDefaultHyperlinkStyle' trống trước' DataTemplate' trong từ điển tài nguyên 'UserControl' của tôi và để lại' StackPanel' cụ thể được thấy ở trên để thay thế nó bằng định nghĩa riêng của nó. Đáng buồn thay, nó vẫn không hoạt động. Tôi sẽ tiếp tục cố gắng điều ... –

+0

@Mal - Không phải anh quên bao gồm phong cách trong các mẫu dữ liệu riêng của mình: ' '? –

Các vấn đề liên quan