2010-11-09 12 views

Odpowiedz

18

Zrobiłem to wcześniej, ponieważ chcieliśmy móc używać tego samego kontrolera dla DataGrid i PropertyGrid. Wiele rzeczy musi zostać zmienionych (np. Wyrównanie, przewijanie, pozycjonowanie strzałek sortowania itp.). Jest wiele sposobów na napisanie całego rozwiązania, ale powinno zacząć. Jest to przykład z autogenerowanymi kolumnami TextColumns, ale można go łatwo zmodyfikować, aby korzystać z innych typów kolumn.

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> 

I gdy kolumny są generowane odwrócić ich pozycji i obraca TextBlocks i otaczaniem (Jest to lepsze, niż obrót DataGridCell chodzi o położenie, plama 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

Dzięki! Działa całkiem nieźle, poziomy pasek przewijania po włączeniu pojawia się u góry (co należy się spodziewać), a zmiana rozmiaru nagłówka jest dziwna (również można się tego spodziewać), ale jest to dobry punkt wyjścia dla mnie. Czy masz szansę na opublikowanie całego rozwiązania? Byłoby to bardzo doceniane;) – eriksmith200

+0

Przepraszam, nie mogę. Jest wbudowany w rozwiązanie, które jest własnością mojej poprzedniej firmy. Mogę Ci pomóc w szczegółach, jeśli publikujesz pytania, ale nie mogę przesłać całego rozwiązania. Powodzenia! –

+0

OK dziękuję, na razie wystarczy, że prototypuję jakiś interfejs użytkownika :) – eriksmith200

7

Uprościliśmy nieco wcześniejsze rozwiązanie. Nie lubię czarnej magii z dodatkowym scrollviewerem, więc jej nie używam. Zamiast tego używam dodatkowej transformacji skali.

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

W przypadku predefiniowanej listy colums możliwe jest transfom komórki zawartość bezpośrednio w 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> 

Pozwala to całkowicie uciec codebehind.

2

Znalazłem to podejście bardzo użyteczne, ja jednak zrobił obrót i mirroring:

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

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

Używając mirroring Mam pole na końcu lista kolumn u dołu zamiast u góry.

16

Naprawdę stoję tu na ramionach gigantów :-), ale mam dodatkowe ulepszenie.

@dimaKudr zasugerował sposób przekształcania predefiniowanych kolumn bez kodu z tyłu, a @FrankE uściślił kolejność kolumn. To, co dodaję, to sposób przekształcania kolumn generowanych automatycznie (AutoGenerateColumns="True") za pomocą szablonu DataGrid.CellStyle. Więc kompletne (i dość eleganckie) rozwiązanie to:

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