2010-11-09 28 views

Répondre

18

Je l'ai fait plus tôt puisque nous voulions être en mesure d'utiliser le même contrôle pour un DataGrid et un PropertyGrid. Beaucoup de choses doivent être changées (comme l'alignement, le défilement, le positionnement des tri-flèches etc.). Il y a beaucoup de code pour poster toute la solution, mais cela devrait vous aider à démarrer. Ceci est un exemple avec TextColumns autogénéré mais vous pouvez facilement le modifier pour utiliser d'autres types de colonnes.

alt text

<ScrollViewer Name="c_dataGridScrollViewer" 
       Loaded="c_dataGridScrollViewer_Loaded" 
       VerticalScrollBarVisibility="Auto" 
       HorizontalScrollBarVisibility="Auto"> 
    <DataGrid x:Name="c_dataGrid" 
       HorizontalAlignment="Left" 
       VerticalAlignment="Top" 
       AutoGeneratedColumns="c_dataGrid_AutoGeneratedColumns" 
       HorizontalScrollBarVisibility="Hidden" 
       VerticalScrollBarVisibility="Hidden"> 
     <DataGrid.ColumnHeaderStyle> 
      <Style TargetType="{x:Type DataGridColumnHeader}"> 
       <Setter Property="LayoutTransform"> 
        <Setter.Value> 
         <TransformGroup> 
          <RotateTransform Angle="90"/> 
         </TransformGroup> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </DataGrid.ColumnHeaderStyle> 
     <DataGrid.LayoutTransform> 
      <TransformGroup> 
       <RotateTransform Angle="-90"/> 
      </TransformGroup> 
     </DataGrid.LayoutTransform> 
    </DataGrid> 
</ScrollViewer> 

Et quand les colonnes sont générées, nous inverser leurs positions et tourne les TextBlocks et TextBoxes (ce qui est mieux que la rotation du DataGridCell en termes d'alignement, flou, etc.)

private void c_dataGridScrollViewer_Loaded(object sender, RoutedEventArgs e) 
{ 
    // Add MouseWheel support for the datagrid scrollviewer. 
    c_dataGrid.AddHandler(MouseWheelEvent, new RoutedEventHandler(DataGridMouseWheelHorizontal), true); 
} 

private void DataGridMouseWheelHorizontal(object sender, RoutedEventArgs e) 
{ 
    MouseWheelEventArgs eargs = (MouseWheelEventArgs)e; 
    double x = (double)eargs.Delta; 
    double y = c_dataGridScrollViewer.VerticalOffset; 
    c_dataGridScrollViewer.ScrollToVerticalOffset(y - x); 
} 

private void c_dataGrid_AutoGeneratedColumns(object sender, EventArgs e) 
{ 
    TransformGroup transformGroup = new TransformGroup(); 
    transformGroup.Children.Add(new RotateTransform(90)); 
    foreach (DataGridColumn dataGridColumn in c_dataGrid.Columns) 
    { 
     if (dataGridColumn is DataGridTextColumn) 
     { 
      DataGridTextColumn dataGridTextColumn = dataGridColumn as DataGridTextColumn; 

      Style style = new Style(dataGridTextColumn.ElementStyle.TargetType, dataGridTextColumn.ElementStyle.BasedOn); 
      style.Setters.Add(new Setter(TextBlock.MarginProperty, new Thickness(0, 2, 0, 2))); 
      style.Setters.Add(new Setter(TextBlock.LayoutTransformProperty, transformGroup)); 
      style.Setters.Add(new Setter(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center)); 

      Style editingStyle = new Style(dataGridTextColumn.EditingElementStyle.TargetType, dataGridTextColumn.EditingElementStyle.BasedOn); 
      editingStyle.Setters.Add(new Setter(TextBox.MarginProperty, new Thickness(0, 2, 0, 2))); 
      editingStyle.Setters.Add(new Setter(TextBox.LayoutTransformProperty, transformGroup)); 
      editingStyle.Setters.Add(new Setter(TextBox.HorizontalAlignmentProperty, HorizontalAlignment.Center)); 

      dataGridTextColumn.ElementStyle = style; 
      dataGridTextColumn.EditingElementStyle = editingStyle; 
     } 
    } 
    List<DataGridColumn> dataGridColumns = new List<DataGridColumn>(); 
    foreach (DataGridColumn dataGridColumn in c_dataGrid.Columns) 
    { 
     dataGridColumns.Add(dataGridColumn); 
    } 
    c_dataGrid.Columns.Clear(); 
    dataGridColumns.Reverse(); 
    foreach (DataGridColumn dataGridColumn in dataGridColumns) 
    { 
     c_dataGrid.Columns.Add(dataGridColumn); 
    } 
} 
+0

Merci! Cela marche plutôt bien, la barre de défilement horizontale lorsqu'elle est activée apparaît en haut (ce qui est à prévoir) et le comportement de redimensionnement de l'en-tête est bizarre (aussi à prévoir) mais c'est un bon point de départ pour moi. Une chance de poster votre solution entière? Serait très apprécié;) – eriksmith200

+0

Désolé, je ne peux pas. C'est intégré dans la solution qui est propre à mon entreprise précédente. Je peux vous aider sur des questions spécifiques si vous postez des questions mais je ne peux pas télécharger la solution entière. Bonne chance! –

+0

Ok merci, pour l'instant il suffit que je prototyper une interface utilisateur :) – eriksmith200

7

J'ai simplifié un peu la solution précédente. Je n'aime pas la magie noire avec scrollviewer supplémentaire, donc je ne l'utilise pas. Mais à la place, j'utilise une transformation d'échelle supplémentaire.

<DataGrid.LayoutTransform> 
    <TransformGroup> 
     <RotateTransform Angle="-90"/> 
     <ScaleTransform ScaleX="1" ScaleY="-1" /> 
    </TransformGroup> 
</DataGrid.LayoutTransform> 

<DataGrid.ColumnHeaderStyle> 
    <Style TargetType="{x:Type DataGridColumnHeader}" 
      BasedOn="{StaticResource {x:Type DataGridColumnHeader}}"> 
     <Setter Property="LayoutTransform"> 
      <Setter.Value> 
       <TransformGroup> 
        <RotateTransform Angle="-90"/> 
        <ScaleTransform ScaleX="1" ScaleY="-1" /> 
       </TransformGroup> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</DataGrid.ColumnHeaderStyle> 

En cas de liste prédéfinie de colums il est possible de directement transfom contenu des cellules en XAML:

<Style x:Key="TextCellStyle" TargetType="{x:Type TextBlock}"> 
    <Setter Property="LayoutTransform"> 
     <Setter.Value> 
      <TransformGroup> 
       <RotateTransform Angle="-90"/> 
       <ScaleTransform ScaleX="1" ScaleY="-1" /> 
      </TransformGroup> 
     </Setter.Value> 
    </Setter> 
</Style> 

Cela vous permet échapper complètement behind.

2

J'ai trouvé cette approche très utile, je l'ai cependant une rotation et une mise en miroir:

TransformGroup transformGroup = new TransformGroup(); 
transformGroup.Children.Add(new RotateTransform(90)); 
transformGroup.Children.Add(new MatrixTransform(-1, 0, 0, 1, 0, 0)); 

ou en XAML:

<!-- we rotate the whole DataGrid by -90 degree and then mirror via y-Axis so that it is docked vertically to the left side--> 
<DataGrid.LayoutTransform> 
    <TransformGroup> 
     <RotateTransform Angle="90"/> 
     <MatrixTransform Matrix="-1,0,0,1,0,0"/> 
    </TransformGroup> 
</DataGrid.LayoutTransform> 

En utilisant le mirroring je le terrain à la fin de la liste des colonnes en bas au lieu d'en haut.

16

Je suis vraiment debout sur les épaules des géants ici :-) mais, j'ai une amélioration supplémentaire. @dimaKudr a suggéré un moyen de transformer des colonnes prédéfinies sans code derrière, et @FrankE a raffiné l'ordre des colonnes. Ce que j'ajoute est un moyen de transformer des colonnes générées automatiquement (AutoGenerateColumns="True"), en utilisant le modèle DataGrid.CellStyle. Donc, la solution complète (et très élégant) est:

<DataGrid ItemsSource="{Binding YourObservableCollection}" 
     AutoGenerateColumns="True" 
     AutoGeneratingColumn="OnAutoGeneratingColumn"> 
    <DataGrid.LayoutTransform> 
     <TransformGroup> 
      <RotateTransform Angle="90"/> 
      <MatrixTransform Matrix="-1,0,0,1,0,0"/> 
     </TransformGroup> 
    </DataGrid.LayoutTransform> 
    <DataGrid.ColumnHeaderStyle> 
     <Style TargetType="{x:Type DataGridColumnHeader}" 
       BasedOn="{StaticResource {x:Type DataGridColumnHeader}}"> 
      <Setter Property="LayoutTransform"> 
       <Setter.Value> 
        <TransformGroup> 
         <RotateTransform Angle="-90"/> 
         <ScaleTransform ScaleX="1" ScaleY="-1" /> 
        </TransformGroup> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </DataGrid.ColumnHeaderStyle> 
    <DataGrid.CellStyle> 
     <Style TargetType="DataGridCell"> 
      <Setter Property="LayoutTransform"> 
       <Setter.Value> 
        <TransformGroup> 
         <RotateTransform Angle="-90"/> 
         <ScaleTransform ScaleX="1" ScaleY="-1" /> 
        </TransformGroup> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </DataGrid.CellStyle> 
</DataGrid>