2012-05-05 25 views
0

我有一個DataGrid:如何在DataGrid的ScrollViewer中添加內容?

<DataGrid ...></DataGrid> 

某處有默認模板,有一個ScrollViewer。我想在裏面添加內容。目前,我這樣做:

<Grid> 
    <DataGrid Grid.Row="0">...</DataGrid> 

    <Canvas Width="128" VerticalAlignment="Stretch" HorizontalAlignment="Left" Grid.Row="0" Margin="0,25,0,0"> 
     <Rectangle Width="32" Height="256" Canvas.Top="0" Canvas.Left="0" Stroke="Black" StrokeThickness="2" /> 
    </Canvas> 
</Grid> 

,看起來像這樣:

enter image description here

也就是說,在畫布獲取網格內繪製。這非常棒,但畫布不會隨數據網格一起滾動。現在我意識到我可能需要改變控制模板,把畫布上滾動查看器中:

<DataGrid> 
    <ControlTemplate> 
     <ScrollViewer> 
      <Grid> 
       <ContentPresenter Grid.Row="0" /> 

       <Canvas Width="128" VerticalAlignment="Stretch" HorizontalAlignment="Left" Grid.Row="0" Margin="0,25,0,0"> 
        <Rectangle Width="32" Height="256" Canvas.Top="0" Canvas.Left="0" Stroke="Black" StrokeThickness="2" /> 
       </Canvas> 
      </Grid> 
     </ScrollViewer> 
    </ControlTemplate> 
</DataGrid> 

然而,這是給我的錯誤:

A first chance exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll

Additional information: Items collection must be empty before using ItemsSource.

如何在畫布內滾動條使其與內容一起滾動?

回答

2

DataGrid是ItemsControl,ItemsControl的ContentProperty是Items屬性。這裏的反編譯源,注意ContentProperty屬性:

[DefaultEvent("OnItemsChanged"), DefaultProperty("Items")] 
[ContentProperty("Items")] 
[StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(FrameworkElement))] 
[Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] // cannot be read & localized as string 
public class ItemsControl : Control, IAddChild, IGeneratorHost 
{ 

這意味着,如果你做這樣的事情:

<DataGrid> 
    <SomethingHere> 
</DataGrid> 

然後<SomethingHere> - 這是內容 - 應用到Items財產。如果隨後綁定到ItemsSource屬性,則會看到您看到的錯誤 - 「在使用ItemsSource之前,Items集合必須爲空。」

如果您用過

<DataGrid> 
    <DataGrid.Template> 
     <ControlTemplate> ... 

你不會得到錯誤。

在任何情況下,最好使用Blend或VS11提取DataGrid的完整ControlTemplate並修改它,例如

<Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}" TargetType="{x:Type Button}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Button}"> 
        <Grid> 
         <Rectangle x:Name="Border" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" SnapsToDevicePixels="True"/> 
         <Polygon x:Name="Arrow" Fill="Black" HorizontalAlignment="Right" Margin="8,8,3,3" Opacity="0.15" Points="0,10 10,10 10,0" Stretch="Uniform" VerticalAlignment="Bottom"/> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsMouseOver" Value="True"> 
          <Setter Property="Stroke" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/> 
         </Trigger> 
         <Trigger Property="IsPressed" Value="True"> 
          <Setter Property="Fill" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/> 
         </Trigger> 
         <Trigger Property="IsEnabled" Value="False"> 
          <Setter Property="Visibility" TargetName="Arrow" Value="Collapsed"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
    <Style x:Key="DataGridStyle1" TargetType="{x:Type DataGrid}"> 
     <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
     <Setter Property="BorderBrush" Value="#FF688CAF"/> 
     <Setter Property="BorderThickness" Value="1"/> 
     <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/> 
     <Setter Property="ScrollViewer.CanContentScroll" Value="true"/> 
     <Setter Property="ScrollViewer.PanningMode" Value="Both"/> 
     <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type DataGrid}"> 
        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True"> 
         <ScrollViewer x:Name="DG_ScrollViewer" Focusable="false"> 
          <ScrollViewer.Template> 
           <ControlTemplate TargetType="{x:Type ScrollViewer}"> 
            <Grid> 
             <Grid.ColumnDefinitions> 
              <ColumnDefinition Width="Auto"/> 
              <ColumnDefinition Width="*"/> 
              <ColumnDefinition Width="Auto"/> 
             </Grid.ColumnDefinitions> 
             <Grid.RowDefinitions> 
              <RowDefinition Height="Auto"/> 
              <RowDefinition Height="*"/> 
              <RowDefinition Height="Auto"/> 
             </Grid.RowDefinitions> 
             <Button Command="{x:Static DataGrid.SelectAllCommand}" Focusable="false" Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> 
             <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> 
             <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.Row="1"/> 
             <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Grid.Row="1" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/> 
             <Grid Grid.Column="1" Grid.Row="2"> 
              <Grid.ColumnDefinitions> 
               <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> 
               <ColumnDefinition Width="*"/> 
              </Grid.ColumnDefinitions> 
              <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/> 
             </Grid> 
            </Grid> 
           </ControlTemplate> 
          </ScrollViewer.Template> 
          <Grid> 
           <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 

           <!-- your canvas here --> 
           <Canvas Width="128" VerticalAlignment="Stretch" HorizontalAlignment="Left" Grid.Row="0" Margin="0,25,0,0"> 
            <Rectangle Width="32" Height="256" Canvas.Top="0" Canvas.Left="0" Stroke="Black" StrokeThickness="2" /> 
           </Canvas> 
          </Grid> 
         </ScrollViewer> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
     <Style.Triggers> 
      <Trigger Property="IsGrouping" Value="true"> 
       <Setter Property="ScrollViewer.CanContentScroll" Value="false"/> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</Window.Resources> 
<Grid> 
    <DataGrid HorizontalAlignment="Left" Margin="125,110,0,0" VerticalAlignment="Top" Height="134" Width="258" Style="{DynamicResource DataGridStyle1}"/> 

</Grid> 
+0

只是一個側面的問題 - 你是如何使用Visual Studio 2011提取默認模板的? – Tower

+0

@rFactor:是的VS11。 – Phil

+0

我的意思是*你是怎麼做到的? – Tower