2010-08-17 54 views
4

我已經通過覆蓋其控件模板爲我的WPF數據網格創建了自定義樣式 - 沒有什麼不尋常的,只是複製了原始模板並對其進行了修改。不幸的是,當繪製網格時,我的ViewModel的全限定類名顯示在頭部(ViewModel恰好是包含DataGrid的UserControl的DataContext)。使用史努比,我縮小了哪個元素在模板中顯示這個類的名字:爲什麼WPF DataGrid在標題中顯示類名稱?

<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的內容嗎?

P.S.要回答下面的評論,我指定了正確的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> 
+0

喲知道,默認的ToString()給出的類名,對不對?所以也許你錯過了Path = ...或其他東西。 – 2010-08-17 14:13:51

+0

我已更新我的問題以澄清您的評論。 – Naresh 2010-08-17 15:01:26

+0

嗨naresh, 你可以請分享編輯過的模板。 1)通過實現DataGridColumnHeaderPresenter派生自Border,因爲它是一個內容控件,您可以將任何元素指定爲子項。在這種情況下,它是一個TextBlock。 2)那 - 我們必須完整地檢查模板。然後,只有我們能夠得出結論。 3)是,DataGridTextColumn的Header屬性。你已經分配的。 http://msdn.microsoft.com/en-us/library/microsoft.windows.themes.datagridheaderborder。aspx – 2010-08-17 20:53:54

回答

7

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> 
+0

就是這樣!我不知道我從哪裏拿到原始模板,但用ContentPresenter替換TextBlock的確有竅門。非常感謝! – Naresh 2010-08-24 13:09:36

相關問題