问题与GridViewRowPresenter
解决方案是树与其他列密不可分。我想你需要它是分开的,这样你就可以只水平放置ScrollViewer
围绕列,我怀疑这对您链接的文章中的项目是否容易(如果可能)进行。
我为了解决这个问题而拼凑起来的这个项目的边缘相当粗糙。有许多问题需要单独解决,但我没有进行微调:
- 模板和样式以使线条匹配,以及其他视觉调整。
- 重新介绍
GridView
标题和列的链接项目的各个方面。
- 用于调整第一列(包含树)大小的拆分器。
就像文章项目一样,我使用了一棵树Type
对象作为数据源。
让它工作的关键是将数据对象包装在一个ExpandingContainer
目的。这个 INPC 课程的重要内容是IsExpanded
属性(用于绑定)和子集合:
public class ExpandingContainer : INotifyPropertyChanged {
public object Payload { get; private set; }
public ObservableCollection<ExpandingContainer> Children { get; private set; }
public ExpandingContainer( object payload ) { ... }
private bool _isexpanded;
public bool IsExpanded {
get { return _isexpanded; }
set {
if ( value == _isexpanded )
return;
_isexpanded = value;
PropertyChanged.Notify( () => IsExpanded );
}
}
public event PropertyChangedEventHandler PropertyChanged = (o,e) => {};
}
至于 XAML,首先让我们获取一些资源:
<!-- bind ExpandingContainer.IsExpanded to TreeViewItem.IsExpanded -->
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>
<!-- for binding ExpandingContainer.IsExpanded to visibility later -->
<BooleanToVisibilityConverter x:Key="boolvis" />
<!-- the TreeViewItems should display the Type's name -->
<HierarchicalDataTemplate DataType="{x:Type loc:ExpandingContainer}"
x:Key="treeViewSide"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Payload.Name}" />
</HierarchicalDataTemplate>
<!-- the column side are naively simple, the ItemsControl of children has its
visibility bound to ExpandingContainer, but the "columns" are just
StackPanels of TextBlocks -->
<HierarchicalDataTemplate DataType="{x:Type loc:ExpandingContainer}"
x:Key="columnSide">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="10,0" />
</Style>
</StackPanel.Resources>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Payload.IsAbstract}" />
<TextBlock Text="{Binding Payload.Namespace}" />
<TextBlock Text="{Binding Payload.GUID}" />
</StackPanel>
<ItemsControl ItemsSource="{Binding Children}"
Visibility="{Binding IsExpanded, Converter={StaticResource boolvis}}" />
</StackPanel>
</HierarchicalDataTemplate>
<!-- a style can't refer to itself, so this was just to apply it to all ItemsControls -->
<Style TargetType="ItemsControl">
<Setter Property="ItemTemplate"
Value="{StaticResource columnSide}" />
</Style>
我最初尝试嵌套水平方向ScrollViewer
包含仅垂直内的右列ScrollViewer
那是负责的TreeView
,但这产生了一个奇怪的要求,即您必须滚动到底部才能水平滚动。所以我把它们进一步分开,把ScrollViewer
并排。
为了使垂直滚动条保持在最右侧,我将两个滚动条隐藏在TreeView
并仅使用列周围的滚动条。同步垂直滚动是在代码隐藏中完成的,但对于更 MVVM 的方式来执行此操作,您可以创建附加行为以方便将它们相互绑定。
<DockPanel>
<ScrollViewer VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden"
DockPanel.Dock="Left"
Name="treescroller">
<TreeView ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource treeViewSide}"
Padding="0,0,0,20">
</TreeView>
</ScrollViewer>
<ScrollViewer Name="columnscroller"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
ScrollChanged="columnscroller_ScrollChanged">
<ItemsControl ItemsSource="{Binding Items}" />
</ScrollViewer>
</DockPanel>
最后,代码隐藏的重要部分(减去创建数据对象并设置DataContext
财产):
private void columnscroller_ScrollChanged( object sender, ScrollChangedEventArgs e ) {
treescroller.ScrollToVerticalOffset( columnscroller.VerticalOffset );
}
希望它能有所帮助,或者至少提供一个不同的视角。
如果我真的需要一款能够满足我能想到的混合动力车的所有需求的好车TreeView
+ListView
,我可能会先看看专业的控件,然后再花必要的时间来完善本土解决方案。当这样的显示要求比较简单的时候,这种东西比较好。