2012-01-06 18 views
13

Me preguntaba si en una cuadrícula de datos WPF en .NET 4.0, es posible tener una fila estática.Freeze DataGrid Fila

Lo que estoy tratando de lograr es crear una fila estática (fila 0), que siempre se mostrará en la parte superior cuando la cuadrícula de datos se desplaza hacia abajo.

La idea es que la fila 0 siempre estará visible a medida que el usuario se desplaza por la cuadrícula de datos.

Gracias.

+0

¿Te refieres a las columnas? ¿O te refieres a las columnas y la fila 0? – RvdK

+1

Coloque el GridViewHeaderRowPresenter en un ScrollView con barras de desplazamiento ocultas. Coloque el ItemsPresenter en un segundo ScrollView con ambas barras de desplazamiento habilitadas. – Dotnet

+0

No, me refiero a la fila.Cuando te desplazas hacia abajo en la cuadrícula de datos, perderás la vista de la fila 0. Pero siempre quiero ver la fila 0. Así que a medida que se desplaza para decir que la fila 360, la fila 0 seguirá estando a la vista como un encabezado. Espero que tenga sentido. – user101010101

Respuesta

0

No estoy seguro acerca de las filas, pero puede congelar las columnas con FrozenColumnCount. De esta manera, siempre será visible. Debería haber una propiedad de congelación.

+3

y luego usa RotateTransform :) –

+2

¿No hay otra manera? Parece extraño que esto no se puede hacer. – user101010101

+0

No es lo que sé de – Sulby

6

Esta "solución simple" es solo para un pie de página freezable, la solución de encabezado congelado sería un poco diferente (y mucho más sencilla, simplemente juega con HeaderTeamplate) coloca un panel de pila con tantos elementos apilados como quieras)

Así que necesitaba una fila de pie de página que fuera freezable, no pude encontrar nada durante meses, así que finalmente decidí dejar de ser flojo e investigar.

Así que si necesita un pie de página, lo esencial es encontrar un lugar en la plantilla de DataGrid entre las filas y el scrollviewer horizontal donde puede exprimir Grid.Row adicional con ItemsControl with Cells.

plan de ataque:

En primer lugar, extraer la plantilla DataGrid (utilicé Blend). Al conseguir familiarizado con la plantilla, tenga en cuenta las partes en orden:

PART_ColumnHeadersPresenter 
PART_ScrollContentPresenter 
PART_VerticalScrollBar 

justo debajo PART_VerticalScrollBar, hay una rejilla (Voy a publicar aquí para mayor claridad)

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

Esa es la rejilla modifiqué para incluir una "fila de freezable/pie de página". Voy a poco difícil que el código de colores, y vuelva a colocar Encuadernación con hoperfully votos propiedades de "fingir" para simplicidad (Voy a marcarlos "MyViewModel.SomeProperty por lo que son fáciles de ver):

<Grid Grid.Column="1" Grid.Row="2" x:Name="PART_DataGridColumnsVisualSpace"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/> 
     <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <ScrollBar Grid.Column="2" Grid.Row="3" Name="PART_HorizontalScrollBar" Orientation="Horizontal" 
      Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" 
      Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" 
      Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/> 

    <Border x:Name="PART_FooterRowHeader" Grid.Row="1" Height="30" Background="Gray" BorderBrush="Black" BorderThickness="0.5"> 
    <TextBlock Margin="4,0,0,0" VerticalAlignment="Center">MY FOOTER</TextBlock> 
    </Border> 
    <ItemsControl x:Name="PART_Footer" ItemsSource="{Binding MyViewModel.FooterRow}" 
       Grid.Row="1" Grid.Column="1" Height="30"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Border Background="Gray" BorderThickness="0,0,0.5,0.5" BorderBrush="Black"> 
        <!-- sticking a textblock as example, i have a much more complex control here--> 
        <TextBlock Text="{Binding FooterItemValue}"/> 
       </Border> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
     <ItemsControl.Template> 
      <ControlTemplate> 
       <ScrollViewer x:Name="PART_Footer_ScrollViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" 
          CanContentScroll="True" Focusable="false"> 
        <StackPanel IsItemsHost="True" Orientation="Horizontal"/> 
       </ScrollViewer> 
      </ControlTemplate> 
     </ItemsControl.Template> 
    </ItemsControl> 
</Grid> 

También añadir a responden cuadrícula de datos para desplazarse y cambiar el tamaño de la cabecera

<DataGrid ... ScrollViewer.ScrollChanged="OnDatagridScrollChanged" 

<Style TargetType="DataGridColumnHeader"> 
    <EventSetter Event="SizeChanged" Handler="OnDataColumnSizeChanged"/> 
</Style> 

Ahora, de vuelta en .xaml.cs

Básicamente se necesitan dos cosas principales:

(1) de sincronización columna de resi ze (de modo que cambia el tamaño de celda de pie correspondiente) (2) sincronización cuadrícula de datos de desplazamiento con desplazamiento pie de página

//syncs the footer with column header resize 
private void OnDatagridScrollChanged(object sender, ScrollChangedEventArgs e) 
{ 
    if (e.HorizontalChange == 0.0) return; 
    FooterScrollViewer.ScrollToHorizontalOffset(e.HorizontalOffset); 
} 

//syncs scroll 
private void OnDataColumnSizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    //I don't know how many of these checks you need, skip if need to the gist 
    if (!_isMouseDown) return; 
    if (!_dataGridLoaded) return; 
    if (!IsVisible) return; 

    var header = (DataGridColumnHeader)sender; 
    var index = header.DisplayIndex - ViewModel.NumberOfHeaderColumns; 

    if (index < 0 || index >= FooterCells.Count) return; 

    FooterCells[index].Width = e.NewSize.Width; 
} 

//below referencing supporting properties: 
private ScrollViewer _footerScroll; 
private ScrollViewer FooterScrollViewer 
{ 
    get { 
     return _footerScroll ?? 
       (_footerScroll = myDataGrid.FindVisualChildByName<ScrollViewer>("PART_Footer_ScrollViewer")); 
     } 
} 

//added this so I don't have to hunt them down from XAML every time 
private List<Border> _footerCells; 
private List<Border> FooterCells 
{ 
    get 
    { 
     if (_footerCells == null) 
     { 
      var ic = myDataGrid.FindVisualChildByName<ItemsControl>("PART_Footer"); 
      _footerCells = new List<Border>(); 
      for (var i = 0; i < ic.Items.Count; i++) 
      { 
       var container = ic.ItemContainerGenerator.ContainerFromIndex(i);        
       var border = ((Visual)container).FindVisualChild<Border>(); 
       _footerCells.Add(border); 
      } 
     } 
     return _footerCells; 
    } 
} 

eso es todo! Creo que la parte más importante es el XAML para ver dónde puedes poner tu "fila de Freezable", todo lo demás, como manipular/sincronizar cosas es bastante fácil: casi una línea)

Cuestiones relacionadas