我想要一个水平方向的WPF DataGrid,有人知道解决方案吗?
答案 0 :(得分:19)
我之前已经这样做了,因为我们希望能够对DataGrid
和PropertyGrid
使用相同的控件。很多东西都要改变(比如对齐,滚动,排序箭头的定位等)。有很多代码可以发布整个解决方案,但这应该让你开始。这是使用自动生成的TextColumns的示例,但您可以轻松地将其修改为使用其他列类型。
<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(这比在对齐,模糊等方面旋转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);
}
}
答案 1 :(得分:17)
我真的站在巨人的肩膀上:-)但是,我有一个额外的增强。
@dimaKudr提出了一种转换预定义列而无需代码的方法,并且@FrankE改进了列的顺序。我要添加的是一种使用AutoGenerateColumns="True"
模板转换自动生成的列(DataGrid.CellStyle
)的方法。所以完整(而且相当优雅)的解决方案是:
<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>
答案 2 :(得分:7)
我简化了以前的解决方案。我不喜欢带有额外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>
这允许您完全逃避代码隐藏。
答案 3 :(得分:2)
我发现这种方法非常有用,但我进行了轮换和镜像:
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>
通过使用镜像,我在列表末尾的字段位于底部而不是顶部。
答案 4 :(得分:0)
哇,很好的解决方案,谢谢!它还需要修改上/下和左/右按钮之间的行/列选择开关。我试图在 DataGrid 的 keydown 或 keyup 事件中解决这个问题,但这有点奇怪,来回翻转选择。有人有比下面更好的解决方案吗?这只是通过wat向左移动和向右移动的代码原来是行。
private void c_dataGrid_KeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Tab:
if (Keyboard.IsKeyDown(Key.LeftShift))
{
if (c_dataGrid.SelectedIndex > 0)
{
c_dataGrid.SelectedIndex--;
}
}
else
{
if (c_dataGrid.SelectedIndex < c_dataGrid.Items.Count - 1)
{
c_dataGrid.SelectedIndex++;
}
}
e.Handled = true;
break;
}
}
}