2010-06-21 36 views
12

Tôi có một TabControl mà tôi đã đặt lại. TabItem có một kích hoạt được kích hoạt khi TabItem được chọn để thay đổi văn bản TabItem thành đậm và xanh lá cây. Vấn đề tôi có là văn bản trong nội dung của tab cũng được đặt thành màu đậm và màu xanh lục.Cài đặt TabItem màu nền trước cũng đặt màu nền trước TabControl

Tôi có thể giải quyết vấn đề này bằng cách đặt tất cả các điều khiển của tôi trong nội dung tab thành trọng số màu và phông chữ mà tôi muốn, nhưng tôi có phải làm điều này không? Vì vậy, tôi phải đảm bảo rằng mọi khối chữ trong vùng nội dung đều có kiểu đặt màu thành màu đen và phông chữ bình thường.

Làm cách nào tôi có thể đặt phần IsSelected của TabItem để hiển thị màu xanh lục, nhưng chỉ để lại nội dung của tab?

Tôi đã cố gắng đặt nền trước của TabControl thành màu đen, nhưng điều này không hoạt động.

Bạn sẽ thấy từ mẫu mã bên dưới văn bản trên tab đầu tiên có màu xanh lục và tôi muốn màu đen, nhưng không đặt từng điều khiển trong nội dung tab.

Mã mẫu dưới đây:

<Grid> 
    <Grid.Resources> 
     <!-- Tab item --> 
     <Style TargetType="{x:Type TabItem}"> 
      <Setter Property="FontSize" Value="14"/> 
      <Setter Property="MinWidth" Value="200"/> 
      <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type TabItem}"> 
         <Grid> 
          <Border Name="Border" Padding="5,2"> 
           <ContentPresenter ContentSource="Header"/> 
          </Border> 
         </Grid> 
         <ControlTemplate.Triggers> 
          <MultiTrigger> 
           <MultiTrigger.Conditions> 
            <Condition Property="Border.IsMouseOver" Value="True"/> 
            <Condition Property="IsSelected" Value="False"/> 
           </MultiTrigger.Conditions> 
           <Setter Property="FontWeight" Value="Bold"/> 
           <Setter Property="Foreground" Value="Black"/> 
          </MultiTrigger> 

          <MultiTrigger> 
           <MultiTrigger.Conditions> 
            <Condition Property="Border.IsMouseOver" Value="False"/> 
            <Condition Property="IsSelected" Value="False"/> 
           </MultiTrigger.Conditions> 
           <Setter Property="Foreground" Value="Black" /> 
          </MultiTrigger> 

          <Trigger Property="IsSelected" Value="True"> 
           <Setter Property="Foreground" Value="Green"/> 
           <Setter Property="FontWeight" Value="Bold"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

     <!-- Tab control --> 
     <Style TargetType="{x:Type TabControl}"> 
      <Setter Property="SelectedIndex" Value="0"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type TabControl}"> 
         <Grid> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="200" /> 
           <ColumnDefinition Width="*" /> 
          </Grid.ColumnDefinitions> 
          <Border Grid.Column="0" Padding="5" Margin="0,0,5,0" CornerRadius="3"> 
           <StackPanel Orientation="Vertical"> 
            <ScrollViewer VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}"> 
             <TabPanel IsItemsHost="True"/> 
            </ScrollViewer> 
           </StackPanel> 
          </Border> 
          <Border Grid.Column="1" BorderBrush="Black" BorderThickness="0"> 
           <ScrollViewer VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}" Padding="10,0"> 
            <ContentPresenter ContentSource="SelectedContent"/> 
           </ScrollViewer> 
          </Border> 
         </Grid> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

    </Grid.Resources> 

    <TabControl Name="tabControl" TabStripPlacement="Left"> 
     <!-- First tab item --> 
     <TabItem IsSelected="True"> 
      <TabItem.Header> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="Profile"/> 
       </StackPanel> 
      </TabItem.Header> 
      <TextBlock Text="Page 1 Sample Text with no foreground set." FontSize="30"/> 
     </TabItem> 

     <!-- Second tab item --> 
     <TabItem IsSelected="True"> 
      <TabItem.Header> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="Profile"/> 
       </StackPanel> 
      </TabItem.Header> 
      <TextBlock Text="Page 2 Sample Text with foreground set manually." FontSize="30" Foreground="Red"/> 
     </TabItem> 
    </TabControl> 
</Grid> 
+0

Đăng một số mã để tìm hiểu xem có gì sai! – decyclone

+0

Đã thêm mẫu mã theo yêu cầu. – Adrian

Trả lời

0

Mỗi kiểm soát trong WPF được thừa hưởng tài sản từ cha của nó. Vì màu của TabItem là màu đen, con của nó là textblock cũng có màu đen. Bây giờ kể từ khi bạn đã thay đổi toàn bộ màu nền trước của TabItem thành màu xanh lá cây, tất cả các con của nó sẽ kế thừa nó.

Tại đây bạn có thể đặt TabItem.Header hoặc nội dung của nó 'tiền cảnh thành màu xanh lá cây, để nó sẽ không ảnh hưởng đến các nội dung khác trong TabItem. Khác bạn có thể đảo ngược giải pháp.

Else Hãy thử điều này:

<Window.Resources> 
    <DataTemplate x:Key="greenHeaderTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="Profile" 
         FontWeight="Bold" 
         Foreground="Green"/> 
     </StackPanel> 
    </DataTemplate> 
    <DataTemplate x:Key="defaultHeaderTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="Profile"/> 
     </StackPanel> 
    </DataTemplate> 
</Window.Resources> 

<Trigger Property="IsSelected" Value="True">  
    <Setter Property="HeaderTemplate" 
      Value="{StaticResource greenHeaderTemplate}"/> 
</Trigger> 

<TabItem IsSelected="True" HeaderTemplate="{StaticResource defaultHeaderTemplate}"> 
    <TextBlock Text="Page 1 Sample Text with no foreground set." FontSize="30"/> 
</TabItem> 
+0

Cảm ơn Veer, nhưng làm cách nào để thiết lập màu của phông chữ tiêu đề tabitem mà không cần thiết lập nội dung? Tôi hiểu tên mục tiêu, nhưng tôi đã thử một vài cách khác nhau mà không có niềm vui. Tôi tiếp tục nhận được một lỗi nói rằng tiền cảnh không thể được đặt trên một tiêu đề tabitem. – Adrian

+0

@Adrian: Đặt tên cho stackpanel bên trong tiêu đề và sử dụng tên đó trong tên mục tiêu. – Amsakanna

+0

@Veer. Xin lỗi là một nỗi đau, nhưng tôi đã thử điều đó và tôi không thể làm cho nó hoạt động được. Có lẽ tôi đang làm sai (có khả năng!). Bạn có thể đăng một số mã để chỉ cho tôi không? Cảm ơn – Adrian

3

này là khá cũ, nhưng tôi đi qua nó trong khi tìm kiếm một câu trả lời cho một vấn đề tương tự, và tôi thấy câu trả lời cung cấp không bao giờ giúp đỡ. Đây là cách tôi đã sửa lỗi này.

Nếu bạn thay đổi ContentPresenter đến một TextBlock trong mẫu kiểm soát của TabItem của bạn, như thế này:

....stuff above here... 
<ControlTemplate TargetType="{x:Type TabItem}"> 
<Grid> 
    <Border Name="Border" Padding="5,2"> 
     <TextBlock x:Name="TabItemContent" Text="{TemplateBinding Header}"/> 
    </Border> 
</Grid> 
... stuff below here.... 

Sau đó, trong kích hoạt của bạn trên đó kiểm soát mẫu bạn chỉ định targetname trong trigger..ie IsSelected.

...stuff above here... 
<Trigger Property="IsSelected" Value="True"> 
    <Setter Property="Foreground" TargetName="TabItemContent" Value="Green"/> 
    <Setter Property="FontWeight" Value="Bold"/> 
</Trigger> 
... stuff below here ... 

Điều đó sẽ cung cấp cho bạn văn bản màu xanh lá cây khi tab được chọn, và không xanh tất cả các thời điểm khác, khi rời khỏi màu văn bản trong phần còn lại của ứng dụng một mình.

9

Tôi vừa mới gặp vấn đề này rất giống nhau, và sau khi không quan tâm đến nó một chút, tôi nghĩ rằng tôi đã tìm thấy một giải pháp thanh lịch hơn.

Tôi nói thanh lịch hơn vì nó sẽ rời khỏi ContentPresenter còn nguyên vẹn, và áp dụng tiền đặt nền trước và phông chữ cho TextElement của ContentPresenter (về cơ bản là thuộc tính đính kèm nhưng bên cạnh điểm).

Ưu điểm chính của phương pháp này là thay thế ContentPresenter bằng TextBlock ngầm giả định rằng tiêu đề sẽ chỉ chứa văn bản, giới hạn khả năng sử dụng của giải pháp và tạo mã kém mạnh hơn. Rời khỏi ContentPresenter tại chỗ sẽ cho phép bất kỳ nội dung nào, ví dụ: hình ảnh + văn bản.

Một điều nữa bạn sẽ phải làm là đặt tên cho ContentPresenter bạn:

<Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type TabItem}"> 
      <Grid> 
       <Border Name="Border" Padding="5,2"> 
        <ContentPresenter x:Name="CP" ContentSource="Header"/> 
       </Border> 
      </Grid> 
      <ControlTemplate.Triggers> 
       <MultiTrigger> 
        <MultiTrigger.Conditions> 
         <Condition Property="Border.IsMouseOver" Value="True"/> 
         <Condition Property="IsSelected" Value="False"/> 
        </MultiTrigger.Conditions> 
        <Setter Property="TextElement.FontWeight" TargetName="CP" Value="Bold"/> 
        <Setter Property="TextElement.Foreground" TargetName="CP" Value="Black"/>         
       </MultiTrigger>... 

Bây giờ Foreground và FontWeight sẽ không được thừa hưởng bởi các nội dung của TabItem (thử nghiệm).

Enjoy :)

+2

Cảm ơn Gilad, đó chắc chắn là một giải pháp tốt hơn nhiều. Rời khỏi ContentPresenter còn nguyên vẹn chắc chắn là con đường để đi. – thornhill

+0

Tôi chỉ đưa ví dụ này lại với nhau. Tuy nhiên các setters cho 'TextElement.Foreground' và' TextElement.FontWeight' không có hiệu lực. Nếu tôi thêm tên 'grid' cho Grid và sau đó thêm' ', nền của nó trở thành màu đỏ. –

3

Thật không may, nếu bạn thiết lập Foreground (hoặc FontWeight) trên một ContentPresenter bởi một số kích hoạt, bạn vẫn cho rằng tiêu đề sẽ chỉ chứa văn bản.

Nếu bạn đặt Tiêu đề = "SomeHeaderName" (nghĩa là chỉ văn bản), trình ContentPresenter sẽ tạo một TextBlock để lưu trữ văn bản đầu tiên này; ContentPresenter sẽ là cha mẹ (hợp lý) của TextBlock này và do đó, bộ Foreground mới trên ContentPresenter sẽ được thừa kế bởi TextBlock này. Điều này hoạt động ok. Tuy nhiên, nếu Header được gán một phần của cây trực quan, giống như một StackPanel ngang với một hình ảnh và một TextBlock (hoặc thậm chí là một TextBlock), thì cha mẹ hợp lý của StackPanel là TabItem chứ không phải ContentPresenter. Thừa kế hoạt động thông qua cây logic và vì vậy TextBlock bên trong StackPanel cuối cùng sẽ kế thừa Foreground của nó từ TabItem một lần nữa; nền trước được đặt trên ContentPresenter không có bất kỳ ảnh hưởng nào đối với điều này.

Một giải pháp có thể có: một DataTemplate cuối cùng được áp dụng cho một ContentPresenter, do đó TemplatedParent của thư mục gốc của DataTemplate là ContentPresenter; và thừa kế cũng hoạt động thông qua một rào cản TemplatedParent-Child. Vì vậy, nếu bạn có thể thiết lập TabItem.HeaderTemplate thay vì TabItem.Header, thì bạn có thể đặt Foreground trên ContentPresenter của tiêu đề, vì thư mục gốc của HeaderTemplate sẽ kế thừa Foreground từ ContentPresenter. Tuy nhiên, SelectedContent sẽ không vì Foreground không được đặt trên TabItem (và nội dung thừa kế Foreground của nó từ TabItem).

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

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