2014-11-21 60 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