2014-11-21 55 views
4

我需要幫助,因爲我不明白爲什麼來自datatemplate的控件不會繼承窗口資源中定義的樣式。 可能有解決方法嗎?WPF SubControl(如TextBlock)不能從TemplateSelector中的窗口繼承樣式

如果有人能給我一個解決方案,我會非常感激,因爲我花了很多時間去尋找答案。

特此以我爲例。例如,水平模板中的Texblock未對齊:

Udapte: 我已添加背景顏色。該樣式應用於標籤,但不適用於由數據模板定義的totextblock和textbox。

<Window x:Class="WpfApplication3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:localview="clr-namespace:WpfApplication3" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 
     <Style x:Key="{x:Type TextBlock}" TargetType="TextBlock" > 
      <Setter Property="Background" Value="Cyan"/> 
      <Setter Property="HorizontalAlignment" Value="Left"/> 
      <Setter Property="VerticalAlignment" Value="Center"/> 
      <Setter Property="Margin" Value="3"/> 
      <Setter Property="FontFamily" Value="Comic Sans MS"/> 
     </Style> 
     <Style x:Key="{x:Type Label}" TargetType="Label"> 
      <Setter Property="Background" Value="Red"/> 
      <Setter Property="VerticalAlignment" Value="Center" /> 
     </Style> 
     <Style x:Key="{x:Type TextBox}" TargetType="TextBox"> 
      <Setter Property="Background" Value="Cyan"/> 
      <Setter Property="HorizontalAlignment" Value="Left"/> 
      <Setter Property="VerticalAlignment" Value="Center"/> 
      <Setter Property="Margin" Value="3"/> 
     </Style> 
     <Style x:Key="{x:Type ComboBox}" TargetType="ComboBox"> 
      <Setter Property="HorizontalAlignment" Value="Left"/> 
      <Setter Property="VerticalAlignment" Value="Center"/> 
      <Setter Property="Margin" Value="3"/> 
     </Style> 

     <localview:TemplateSelector x:Key="TemplateSelector"> 
      <localview:TemplateSelector.DataTemplateH> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <Label Content="Value"/> 
         <TextBox Text="{Binding Path=SelectedItem.Content ,ElementName=Combo}"/> 
        </StackPanel> 
       </DataTemplate> 
      </localview:TemplateSelector.DataTemplateH> 
      <localview:TemplateSelector.DataTemplateV> 
       <DataTemplate> 
        <StackPanel Orientation="Vertical"> 
         <Label Content="Value"/> 
         <StackPanel Orientation="Horizontal"> 
          <Label Content="new line"/> 
          **<TextBlock Text="{Binding Path=SelectedItem.Content ,ElementName=Combo}" TextAlignment="Right"/>** 
         </StackPanel> 
        </StackPanel> 
        </DataTemplate> 
      </localview:TemplateSelector.DataTemplateV> 
     </localview:TemplateSelector> 

    </Window.Resources> 


    <StackPanel Orientation="Vertical"> 

     <StackPanel> 
      <TextBlock Text="Texblock"/> 
      <TextBox Text="Texblock"/> 
      <StackPanel Orientation="Horizontal"> 
       <Label Content="Value"/> 
       <ComboBox Name="Combo"> 
        <ComboBox.Items> 
         <ComboBoxItem Content="H"/> 
         <ComboBoxItem Content="V"/> 
        </ComboBox.Items> 
       </ComboBox> 
      </StackPanel> 
      <ContentControl ContentTemplateSelector="{StaticResource TemplateSelector}" 
             Content="{Binding Path=SelectedItem.Content ,ElementName=Combo}" /> 
     </StackPanel> 

    </StackPanel> 
</Window> 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Reflection; 


namespace WpfApplication3 
{ 
    public class TemplateSelector : DataTemplateSelector 
    { 

     public DataTemplate DataTemplateH 
     { 
      get; 
      set; 
     } 

     public DataTemplate DataTemplateV 
     { 
      get; 
      set; 
     } 


     public override DataTemplate SelectTemplate(object item, DependencyObject container) 
     { 
      string s = (string)item; 

      if (s == "H") 
       return DataTemplateH; 

      if (s == "V") 
       return DataTemplateV; 

      return base.SelectTemplate(item, container); 
     } 
    } 
} 

回答

3

我只是嘗試了一些簡單的演示和肯定的答案是,你不能在模板之外的某處定義的默認樣式應用到一些TextBlock的模板(包括DataTemplate中和控件模板)。這不會發生在其他控件上,例如Label,TextBox(儘管您也表示Style不適用於TextBox,但我嘗試過,實際上並非如此)。

要解決這個問題,最好的辦法是設置風格明確的TextBlock的是這樣的:

<TextBlock Text="{Binding Path=SelectedItem.Content ,ElementName=Combo}" 
      TextAlignment="Right" Style="{StaticResource {x:Type TextBlock}}"/> 

請注意,正如我所說,這只是需要的TextBlocks 模板(DataTemplate中和ControlTemplate)。

該代碼看起來相當荒謬,但它實際上工作,沒有這樣做,因爲你看到它不會工作。

+1

非常感謝這個適合我的解決方案。對於TextBox,你是對的。 – TFFR 2014-11-21 11:32:55

6

只是爲了闡明一些輕爲什麼TextBlock沒有找到它的含蓄的風格,有WPF中隱含的風格好奇的規則只能由從Control類繼承要素跨邊界模板繼承;不從Control繼承的元素不會探測父模板之外的隱式樣式。

負責此的代碼可以在FrameworkElement發現:

// FindImplicitSytle(fe) : Default: unlinkedParent, deferReference 
internal static object FindImplicitStyleResource(
    FrameworkElement fe, 
    object resourceKey, 
    out object source) 
{ 
    ... 

    // For non-controls the implicit StyleResource lookup must stop at 
    // the templated parent. Look at task 25606 for further details. 
    DependencyObject boundaryElement = null; 
    if (!(fe is Control)) 
    { 
     boundaryElement = fe.TemplatedParent; 
    } 

    ... 
} 

卡羅爾·斯奈德在微軟explains the reasons for this behavior

我給出的理由是,控件比元素更加明顯,這是很可能應該在任何地方應用隱式的控件風格,在這種風格中,元素的隱式風格應該被普遍應用。這個論點有一個合理的觀點。考慮以下內容:

<StackPanel> 
    <StackPanel.Resources> 
    <Style TargetType="TextBlock"> 
     <Setter Property="FontSize" Value="16"/> 
     <Setter Property="Foreground" Value="Green"/> 
    </Style> 
    </StackPanel.Resources> 

    <TextBlock HorizontalAlignment="Center" Text="Hello!"/> 
    <Button Content="Click me!" Width="200"/> 
    <TextBlock HorizontalAlignment="Center" Text="Please click the button"/> 
</StackPanel> 

按鈕通過最終創建TextBlock並將該字符串添加到TextBlock來顯示字符串。如果按鈕將TextBlock所使用的應用程序定義的隱式的款式,XAML會使這樣:

Example Image

這可能不是你想要的行爲。另一方面,假設您正在創建一個很酷的用戶界面,並且您希望所有的RepeatButton都具有特定的外觀。如果您定義RepeatButton的外觀一次,則即使RepeatButton位於ControlTemplate中,所有RepeatButton也將使用該外觀。

+0

這確實有助於我理解TextBlock(以及其他非控件)的奇怪Style查找行爲,謝謝。這當然應該在首次發佈時被接受(也許OP會考慮這一點並改變他的決定)。在回答OP的問題之前,我不確定你是否知道這個理由,但如果你在試圖回答這個問題的時候才真正瞭解這個問題,那麼你應該投票贊成OP的問題。 (我希望我可以再次投票)。 – 2014-11-22 18:36:02

+0

非常感謝這些有用的解釋,我不知道。 – TFFR 2014-11-24 12:25:00