C# WPF子控制(如TextBlock)不';t使用TemplateSelector从窗口继承样式

C# WPF子控制(如TextBlock)不';t使用TemplateSelector从窗口继承样式,c#,wpf,xaml,C#,Wpf,Xaml,我需要帮助,因为我不明白为什么来自datatemplate的控件不继承窗口资源中定义的样式。 可能有解决办法吗 如果有人能给我一个解决方案,我会非常感激,因为我花了很多时间去寻找一些东西。 <Window x:Class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.m

我需要帮助,因为我不明白为什么来自datatemplate的控件不继承窗口资源中定义的样式。 可能有解决办法吗

如果有人能给我一个解决方案,我会非常感激,因为我花了很多时间去寻找一些东西。

<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);
        }
    }
}
这是我的前任。例如,水平模板中的Texblock未对齐:

Udapte: 我添加了背景色。样式应用于标签,但不应用于datatemplate定义的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);
        }
    }
}

****
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
运用系统反思;
命名空间WpfApplication3
{
公共类TemplateSelector:DataTemplateSelector
{
公共数据模板数据模板
{
得到;
设置
}
公共数据模板数据模板
{
得到;
设置
}
公共覆盖数据模板SelectTemplate(对象项,DependencyObject容器)
{
字符串s=(字符串)项;
如果(s=“H”)
返回数据模板;
如果(s=“V”)
返回数据模板;
返回基地。选择模板(项目、容器);
}
}
}

我刚刚尝试了一些简单的演示,是的,答案是您不能将模板外部定义的默认样式应用于模板内部的某个文本块(包括DataTemplate和ControlTemplate)。其他控件,如Label、TextBox,则不会出现这种情况(虽然您也说过该样式不适用于TextBox,但我尝试过,但事实并非如此)

要解决此问题,最好的方法是为TextBlock显式设置样式,如下所示:

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

请注意,正如我所说,它只适用于模板(DataTemplate和ControlTemplate)内部的文本块


代码看起来相当可笑,但实际上是有效的,如果不按您所看到的那样做,它将不起作用。

只是想解释一下为什么
文本块
找不到其隐含的风格,WPF中有一个奇怪的规则,隐式样式仅由从
控件继承的元素跨模板边界继承;不从
控件继承的元素将不会探测父模板之外的隐式样式

负责此操作的代码可在
FrameworkElement
中找到:

//FindImplicitSytle(fe):默认值:取消链接的parent,延迟引用
内部静态对象FindImplicityStyleResource(
框架元素fe,
对象资源键,
输出对象(源)
{
...
//对于非控件,隐式样式资源查找必须在
//模板化的父级。有关更多详细信息,请参阅任务25606。
DependencyObject boundaryElement=null;
如果(!(fe为控制))
{
boundaryElement=fe.TemplatedParent;
}
...
}
微软的卡罗尔·斯奈德:

我被告知的原因是控件比元素更明显,控件的隐式样式很可能应用于所有地方,而元素的隐式样式不太可能被普遍应用。这个论点是有道理的。考虑以下事项:


按钮通过最终创建TextBlock并将字符串添加到TextBlock来显示字符串。如果按钮中的TextBlock使用应用程序定义的隐式样式,XAML将以以下方式呈现:

这可能不是你想要的行为。另一方面,假设您正在创建一个很酷的UI,并且希望所有的RepeatButton都具有特定的外观。如果只定义一次RepeatButton的外观,则所有RepeatButton都将使用该外观,即使RepeatButton位于ControlTemplate内


非常感谢这个适合我的解决方案。对于TextBox,你是对的。这确实帮助我理解TextBlock(以及其他非控件)的奇怪样式行为,谢谢。这当然应该被接受,如果它是第一次张贴(也许OP会考虑这一点,并改变他的决定)。我不确定你在回答OP的问题之前是否知道这个原因,但是如果你在回答这个问题时确实知道这个原因,你应该投OP的问题的赞成票。(我希望我能再次投票)。非常感谢这些我不知道的有用的解释。