Почему WPF DataGrid показывает имя класса в заголовке? - PullRequest
4 голосов
/ 17 августа 2010

Я создал собственный стиль для моей таблицы данных WPF, переопределив его шаблон управления - ничего необычного, просто скопировал исходный шаблон и изменил его.К сожалению, когда отрисовывается сетка, в заголовке появляется полное имя класса моей ViewModel (ViewModel - это DataContext из UserControl, который содержит DataGrid).Используя Snoop, я сузил, какой элемент в шаблоне показывает это имя класса:

<DataGridColumnHeadersPresenter 
 Grid.Column="1" 
 Name="PART_ColumnHeadersPresenter"
 Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>

Визуальное дерево для этой части выглядит так:

PART_ColumnHeadersPresenter (DataGridColumnHeadersPresenter)
    (Grid)
        headerBorder (DataGridHeaderBorder)
            (Border)
                (TextBlock)

Именно этот текстблок, содержащий имя класса!Итак, вопросы:

  1. Почему для Границы требуется TextBlock?
  2. Почему TextBlock инициализируется именем класса DataContext?
  3. Есть ли свойствона уровне DataGrid, который контролирует содержимое этого TextBlock?

PS Чтобы ответить на комментарий ниже, я указываю правильные пути для ItemSource, а также для каждого столбца:

<DataGrid
    ItemsSource="{Binding Path=Orders, Mode=TwoWay}"
    AutoGenerateColumns="False"
    IsReadOnly="True">
    <DataGrid.Columns>
        <DataGridTextColumn
            Header="Creation Time"
            Binding="{Binding Path=CreationTime}"
            CellStyle="{StaticResource LeftAlignedCellStyle}"
            SortMemberPath="CreationTime">
        </DataGridTextColumn>
        ...
    </DataGrid.Columns>
</DataGrid>

Я не вижу места, где я должен привязывать TextBlock к границе заголовка столбца.Даже не знаю, как это имеет смысл!

Основываясь на комментариях Аватара, я делюсь всем своим шаблоном.Смотрите ниже:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Brushes.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <!-- ColumnHeader Gripper Style -->
    <Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
        <Setter Property="Width" Value="8"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Cursor" Value="SizeWE"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border Padding="{TemplateBinding Padding}"
                            Background="{TemplateBinding Background}">
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- DataGridColumnHeader Style -->
    <Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}"/>
        <Setter Property="Foreground" Value="{StaticResource HeaderForegroundBrush}"/>
        <Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
        <Setter Property="BorderThickness" Value="0,1,0,1" />
        <Setter Property="FontFamily" Value="Trebuchet MS" />
        <Setter Property="FontSize" Value="12" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                    <Grid>
                        <themes:DataGridHeaderBorder
                            x:Name="headerBorder"
                            SortDirection="{TemplateBinding SortDirection}"
                            IsHovered="{TemplateBinding IsMouseOver}"
                            IsPressed="{TemplateBinding IsPressed}"
                            IsClickable="{TemplateBinding CanUserSort}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding ="{TemplateBinding Padding}"
                            SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
                            SeparatorBrush="{TemplateBinding SeparatorBrush}">
                            <Border BorderBrush="{StaticResource HeaderInnerBorderBrush}" 
                                    BorderThickness="0,1,0,0">
                                <TextBlock
                                    Text="{Binding}" Margin="7,0,7,0"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
                            </Border>
                        </themes:DataGridHeaderBorder>

                        <Thumb x:Name="PART_LeftHeaderGripper"
                               HorizontalAlignment="Left"
                               Style="{StaticResource ColumnHeaderGripperStyle}"/>
                        <Thumb x:Name="PART_RightHeaderGripper"
                               HorizontalAlignment="Right"
                               Style="{StaticResource ColumnHeaderGripperStyle}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="headerBorder" Property="Background" 
                                    Value="{StaticResource HeaderHighlightedBackgoundBrush}" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="headerBorder" Property="Background" 
                                    Value="{StaticResource HeaderPressedBackgroundBrush}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Right Aligned DataGridColumnHeader Style-->
    <Style x:Key="RightAlignedColumnHeaderStyle" 
           TargetType="{x:Type DataGridColumnHeader}"
           BasedOn="{StaticResource DataGridColumnHeaderStyle}">
        <Setter Property="HorizontalContentAlignment" Value="Right"/>
    </Style>

    <!-- Center Aligned DataGridColumnHeader Style-->
    <Style x:Key="CenterAlignedColumnHeaderStyle" 
           TargetType="{x:Type DataGridColumnHeader}"
           BasedOn="{StaticResource DataGridColumnHeaderStyle}">
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
    </Style>

    <!-- DataGridRowHeader Gripper -->
    <Style x:Key="RowHeaderGripperStyle" TargetType="{x:Type Thumb}">
        <Setter Property="Height" Value="8"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Cursor" Value="SizeNS"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border Padding="{TemplateBinding Padding}"
                            Background="{TemplateBinding Background}"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- DataGridRowHeader Style -->
    <Style x:Key="{x:Type DataGridRowHeader}"
           TargetType="{x:Type DataGridRowHeader}">
        <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}" />
        <Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridRowHeader}">
                    <Grid>
                        <themes:DataGridHeaderBorder 
                            x:Name="headerBorder"
                            IsSelected="{TemplateBinding IsRowSelected}"
                            IsHovered ="{TemplateBinding IsMouseOver}"
                            IsPressed="{TemplateBinding IsPressed}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="1,0,1,1"
                            Padding ="{TemplateBinding Padding}"
                            Orientation="Horizontal"
                            SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
                            SeparatorBrush="{TemplateBinding SeparatorBrush}">
                            <Border BorderBrush="{StaticResource HeaderInnerBorderBrush}"
                                    BorderThickness="0,1,0,0">
                                <StackPanel Orientation="Horizontal">
                                    <ContentPresenter
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                        VerticalAlignment="Center"/>
                                    <Control
                                        SnapsToDevicePixels="false"
                                        Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, Path=(Validation.HasError), Converter={StaticResource bool2VisibilityConverter}}"
                                        Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, Path=ValidationErrorTemplate}" />
                                </StackPanel>
                            </Border>
                        </themes:DataGridHeaderBorder>

                        <Thumb x:Name="PART_TopHeaderGripper"
                               VerticalAlignment="Top"
                               Style="{StaticResource RowHeaderGripperStyle}"/>
                        <Thumb x:Name="PART_BottomHeaderGripper"
                               VerticalAlignment="Bottom"
                               Style="{StaticResource RowHeaderGripperStyle}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="headerBorder" Property="Background" 
                                    Value="{StaticResource HeaderHighlightedBackgoundBrush}" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="headerBorder" Property="Background" 
                                    Value="{StaticResource HeaderPressedBackgroundBrush}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- DataGridElement Styles -->
    <Style x:Key="DataGridElementStyle" TargetType="{x:Type FrameworkElement}">
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="Margin" Value="7 0 7 0" />
    </Style>
    <Style x:Key="LeftAlignedElementStyle" TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource DataGridElementStyle}">
        <Setter Property="HorizontalAlignment" Value="Left" />
    </Style>
    <Style x:Key="CenterAlignedElementStyle" TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource DataGridElementStyle}">
        <Setter Property="HorizontalAlignment" Value="Center" />
    </Style>
    <Style x:Key="RightAlignedElementStyle" TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource DataGridElementStyle}">
        <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>

    <!-- DataGridCell Styles -->
    <Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
        <!-- Remove blue highlight when cell is selected -->
        <Setter Property="Background" Value="Transparent" />
        <!-- Don't change text color when cell is selected -->
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=Foreground}"/>
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style x:Key="LeftAlignedCellStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Grid Background="{TemplateBinding Background}">
                        <ContentPresenter Style="{StaticResource LeftAlignedElementStyle}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Center Aligned DataGridCell Style -->
    <Style x:Key="CenterAlignedCellStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Grid Background="{TemplateBinding Background}">
                        <ContentPresenter Style="{StaticResource CenterAlignedElementStyle}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Right Aligned DataGridCell Style -->
    <Style x:Key="RightAlignedCellStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Grid Background="{TemplateBinding Background}">
                        <ContentPresenter Style="{StaticResource RightAlignedElementStyle}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- SelectAllButton ControlTemplate -->
    <ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}">
        <Grid>
            <Rectangle x:Name="Border" SnapsToDevicePixels="True"
                       Stroke="{StaticResource HeaderBorderBrush}"
                       Fill="{StaticResource HeaderBackgroundBrush}" />
            <Border SnapsToDevicePixels="True" Margin="1,1,1,0"
                    BorderBrush="White" BorderThickness="0,1,0,0" />
            <Polygon x:Name="Arrow"
                     HorizontalAlignment="Right"
                     VerticalAlignment="Bottom"
                     Margin="8,8,3,3"
                     Opacity="0.15"
                     Fill="Black"
                     Stretch="Uniform"
                     Points="0,10 10,10 10,0" />
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="Border" Property="Fill"
                        Value="{StaticResource HeaderHighlightedBackgoundBrush}" />
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter TargetName="Border" Property="Fill"
                        Value="{StaticResource HeaderPressedBackgroundBrush}" />
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter TargetName="Arrow" Property="Visibility" Value="Collapsed" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <!-- DataGrid Style -->
    <Style x:Key="{x:Type DataGrid}" TargetType="{x:Type DataGrid}">
        <Setter Property="Background" Value="{StaticResource DefaultControlBackgroundBrush}"/>
        <Setter Property="Foreground" Value="{StaticResource DefaultControlForegroundBrush}"/>
        <!-- Remove border around the grid -->
        <Setter Property="BorderBrush" Value="{x:Null}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource GridLineColorBrush}" />
        <Setter Property="VerticalGridLinesBrush" Value="{StaticResource GridLineColorBrush}" />
        <Setter Property="AlternatingRowBackground" Value="{StaticResource AlternateRowBackgroundBrush}" />
        <Setter Property="ColumnHeaderStyle" Value="{StaticResource DataGridColumnHeaderStyle}"/>
        <!-- This is needed to force DG to have a non-default value.  Otherwise the DGR.DetailsVisibility cannot have a value of VisibleWhenSelected by default. -->
        <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected" />
        <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
        <!-- Turn off row headers by default. -->
        <Setter Property="HeadersVisibility" Value="Column" />
        <Setter Property="GridLinesVisibility" Value="Horizontal" />
        <Setter Property="ColumnHeaderHeight" Value="32" />
        <Setter Property="RowHeight" Value="32" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGrid}">
                    <Border
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        SnapsToDevicePixels="True"
                        Padding="{TemplateBinding Padding}">
                        <ScrollViewer Focusable="false" Name="DG_ScrollViewer">
                            <ScrollViewer.Template>
                                <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="*"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>

                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="Auto"/>
                                        </Grid.ColumnDefinitions>

                                        <!--Left Column Header Corner -->
                                        <Button 
                                            Command="{x:Static DataGrid.SelectAllCommand}"
                                            Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=CellsPanelHorizontalOffset}"
                                            Focusable="false"
                                            Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.All}}" 
                                            Template="{StaticResource SelectAllButtonTemplate}"/>
                                        <!--Column Headers-->
                                        <DataGridColumnHeadersPresenter 
                                            Grid.Column="1" 
                                            Name="PART_ColumnHeadersPresenter"
                                            Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>

                                        <!--DataGrid content-->
                                        <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />

                                        <ScrollBar
                                            Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Name="PART_VerticalScrollBar"
                                            Orientation="Vertical"
                                            Maximum="{TemplateBinding ScrollableHeight}"
                                            ViewportSize="{TemplateBinding ViewportHeight}"
                                            Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                            Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>

                                        <Grid Grid.Row="2" Grid.Column="1">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
                                                <ColumnDefinition Width="*"/>
                                            </Grid.ColumnDefinitions>
                                            <ScrollBar 
                                                Grid.Column="1"
                                                Name="PART_HorizontalScrollBar"
                                                Orientation="Horizontal"
                                                Maximum="{TemplateBinding ScrollableWidth}"
                                                ViewportSize="{TemplateBinding ViewportWidth}"
                                                Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                                Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
                                        </Grid>
                                    </Grid>
                                </ControlTemplate>
                            </ScrollViewer.Template>
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsGrouping" Value="true">
                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
            </Trigger>
        </Style.Triggers>
    </Style>

</ResourceDictionary>

1 Ответ

7 голосов
/ 24 августа 2010

Шаблон по умолчанию для DataGridColumnHeadersPresenter выглядит примерно так:

<ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
    <Grid>
        <DataGridColumnHeader IsHitTestVisible="False"
            Name="PART_FillerColumnHeader"/>
        <ItemsPresenter />
    </Grid>
</ControlTemplate>

. ItemsPresenter создаст DataGridColumnHeader для каждого столбца, но шаблон также включает в себя один DataGridColumnHeader, который растягиваетсяпо всей сетке, чтобы действовать в качестве фона.У него нет содержимого, поэтому обычно он рисует границу в соответствующей теме.

Однако ваш шаблон DataGridColumnHeader включает TextBlock вместо ContentPresenter, поэтому он будет отображать DataContextв виде строки, независимо от того, является ли она содержимым.Попробуйте использовать ContentPresenter вместо TextBlock:

<Border BorderBrush="{StaticResource HeaderInnerBorderBrush}" 
        BorderThickness="0,1,0,0">
    <ContentPresenter
        Margin="7,0,7,0"
        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Border>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...