WPF水平DataGrid

我想有一个水平方向的WPF DataGrid,有没有人知道一个解决scheme?

我之前做过这个,因为我们希望能够对DataGridPropertyGrid使用相同的控件。 许多东西都必须改变(如排列,滚动,sorting箭头的位置等)。 有很多代码来发布整个解决scheme,但这应该让你开始。 这是自动生成的TextColumns的一个例子,但您可以轻松修改它以使用其他列types。

替代文字

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

当生成列时,我们反转它们的位置并旋转TextBlocks和TextBoxes(这比在alignment,模糊等方面旋转DataGridCell更好)

 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); } } 

我真的站在巨人的肩膀上:-)但是,我有一个额外的增强。

@dimaKudr提出了一种方法来转换预定义的列,而不需要代码,@FrankE改进了列的顺序。 我正在添加的是一种通过使用DataGrid.CellStyle模板来转换自动生成的列( AutoGenerateColumns="True" )的方法。 所以完整(而且非常优雅)的解决scheme是:

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

我简化了一点以前的解决scheme。 我不喜欢额外的scrollviewer黑魔法,所以我不使用它。 但是,我使用额外的规模转换。

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

如果预定义列表,可以直接在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> 

这可以让你彻底逃避代码隐藏。

我发现这个方法非常有用,但我做了一个轮换和镜像:

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

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

通过使用镜像,我有在列底部的领域,而不是在顶部的领域。