2010-11-09 20 views

Antwort

18

Ich habe dies früher gemacht, da wir in der Lage sein wollten, das gleiche Steuerelement für eine DataGrid und eine PropertyGrid zu verwenden. Viele Dinge müssen geändert werden (wie Ausrichtung, Scrollen, Positionieren von Sortierpfeilen usw.). Es gibt viel zu viel Code, um die gesamte Lösung zu veröffentlichen, aber das sollte Ihnen den Einstieg erleichtern. Dies ist ein Beispiel mit automatisch generierten TextColumns, aber Sie können es leicht ändern, um andere Spaltentypen zu verwenden.

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> 

Und wenn die Spalten erzeugt werden, umgekehrt wir ihre Positionen und dreht die Textblocks und Textfelder (Das ist besser als die DataGridCell in Bezug auf die Ausrichtung zu drehen, verschwimmen 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

Danke! Es funktioniert ziemlich gut, die horizontale Bildlaufleiste, wenn aktiviert, erscheint an der Spitze (was zu erwarten ist) und das Verhalten der Header-Größenänderung ist seltsam (auch zu erwarten), aber das ist ein guter Ausgangspunkt für mich. Gibt es eine Chance, dass Sie Ihre gesamte Lösung veröffentlichen? Würde sehr geschätzt werden;) – eriksmith200

+0

Sorry, ich kann nicht. Es ist in die Lösung integriert, die meine vorherige Firma besitzt. Ich kann Ihnen bei Fragen helfen, wenn Sie Fragen stellen, aber ich kann nicht die gesamte Lösung hochladen. Viel Glück! –

+0

Ok danke, für jetzt reicht es, da ich einige UI Prototyping bin :) – eriksmith200

7

Ich habe ein wenig vorherige Lösung vereinfacht. Ich mag keine schwarze Magie mit zusätzlichen Scrollviewer, also benutze ich sie nicht. Stattdessen benutze ich zusätzliche Skalierung.

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

Bei vordefinierten Liste von colums ist es möglich, Zellen Inhalt direkt in XAML transfom:

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

Dieser Code-Behind Sie vollständig entweichen kann.

2

ich dieser Ansatz als sehr nützlich, ich habe jedoch eine Drehung und eine Spiegelung:

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

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

Durch die Verwendung der Spiegelung ich das Feld am Ende haben, die Spaltenliste unten statt oben.

16

Ich stehe wirklich auf den Schultern von Riesen hier :-) aber, ich habe eine zusätzliche Verbesserung.

@dimaKudr schlug eine Möglichkeit vor, vordefinierte Spalten ohne Code zu transformieren, und @FrankE verfeinerte die Reihenfolge der Spalten. Was ich hinzufüge, ist eine Möglichkeit, automatisch generierte Spalten (AutoGenerateColumns="True") zu transformieren, indem Sie die Vorlage DataGrid.CellStyle verwenden. Also die komplette (und recht elegante) Lösung ist:

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