1

简而言之,问题标题说明了一切。对于那些想要更多细节的人,这里是我的问题的症结所在:我需要对控件ControlTemplate中的DataGridColumnHeader元素应用自定义DataGrid,但我还需要根据最靠近标题的单元格数据对它们进行不同的样式设置。但是,当我在一个元素上同时设置ContentTemplateSelector 属性时,不会调用设置为属性值的。注释掉属性设置证实了这种情况,因为现在将调用该元素。TemplateDataGridColumnHeaderDataTemplateSelectorContentTemplateSelectorTemplateDataTemplateSelector

是的,我知道你们喜欢看一些代码,但是我已经将整个DataGrid控件完全模板化为看起来像 Excel,所以你可以想象,我有太多代码要在这里显示。但只是为了取悦你代码饥饿的开发人员,我在一个更简单的例子中重新创建了我的问题......让我们首先看看 XAML:

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Local="clr-namespace:WpfApp1"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid>
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
            <DataGrid.Items>
                <System:String>One</System:String>
                <System:String>Two</System:String>
                <System:String>Three</System:String>
            </DataGrid.Items>
            <DataGrid.Resources>
                <Local:StringDataTemplateSelector x:Key="StringDataTemplateSelector" />
                <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
                    <Setter Property="ContentTemplateSelector" Value="{StaticResource StringDataTemplateSelector}" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                                <Grid>
                                    <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" />
                                    <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" />
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGrid.Resources>
        </DataGrid>
    </Grid>
</Window>

现在最简单的DataTemplateSelector类:

using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace WpfApp1
{
    public class StringDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            Debugger.Break();
            return null;
        }
    }
}

在 XAML 中,我们看到一个DataGrid,只有一个DataGridTemplateColumn和三个字符串值,每行一个,以及一些资源。该部分中有一个StyleforDataGridColumnHeader元素,对其Resource进行了最简单的ControlTemplate设置,它只包括默认的所需命名部分ControlTemplate

如果您按原样运行应用程序,那么它当前不会Debugger.Break()在类中的方法处中断StringDataTemplateSelector。这是出乎意料的。如果您现在注释掉 中的Template属性设置Style并再次运行应用程序,那么您现在将看到程序执行现在将在该Debugger.Break()方法处中断,正如预期的那样。

更多信息

ContentControl.ContentTemplateSelector在 MSDN属性页面的备注部分中,它指出

如果同时设置了ContentTemplateSelectorContentTemplate属性,则忽略此属性。

但是,它没有提及该属性,并且在 MSDN 的“属性”页面上Template也没有提及这一点。Control.Template

此外,我使用一个简单的控件尝试了相同的设置Button,并且可以确认同时设置ContentTemplateSelectorContentTemplate属性不会阻止StringDataTemplateSelector类被调用:

<ItemsControl>
    <ItemsControl.Resources>
        <Local:StringDataTemplateSelector x:Key="StringDataTemplateSelector" />
        <Style TargetType="{x:Type Button}">
            <Setter Property="ContentTemplateSelector" Value="{StaticResource StringDataTemplateSelector}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid>
                            <Ellipse Stroke="Red" StrokeThickness="1" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding Height}" />
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.Resources>
    <Button Content="One" />
    <Button Content="Two" />
    <Button Content="Three" />
</ItemsControl>

因此,我所追求的是一种将自定义ControlTemplate元素应用于DataGridColumnHeader对象的方法,但仍然能够DataTemplateSelector在渲染过程中调用该类。

4

1 回答 1

1

在您的控件模板中添加内容演示者?

<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
    <Grid>
           <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" />
           <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" />
           <ContentPresenter></ContentPresenter>
    </Grid>
</ControlTemplate>
于 2018-01-29T16:08:42.370 回答