2

我有一个自定义 TreeListView - 基于标准 TreeView - 具有以下样式:

<Style TargetType="{x:Type c:TreeListView}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type: c:TreeListView}">
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
               <DockPanel>
                  <GridViewHeaderRowPresenter DockPanel.Dock="Top" Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}" />
                  <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
               </DockPanel>
            </Border>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

因为我没有 ScrollViewer,所以内容不会滚动,所以如果内容需要的空间比可用空间多,它看起来像这样:

在此处输入图像描述

所以我添加了一个 ScrollViewer,让样式现在看起来像这样:

<Style TargetType="{x:Type c:TreeListView}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type: c:TreeListView}">
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
               <ScrollViewer Focusable="False" Padding="{TemplateBinding Padding">
                  <DockPanel>
                     <GridViewHeaderRowPresenter DockPanel.Dock="Top" Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}" />
                     <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                  </DockPanel>
               </ScrollViewer>
            </Border>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

随着第一张图片中的内容展开,内容无法滚动,但列标题也会滚动,这是不希望的:D

在此处输入图像描述

谁能帮助我,以便仅滚动内容,而不是绑定到GridViewHeaderRowPresenter的列?

谢谢!

[编辑]

感谢右边的相关链接,我在这里找到了答案。

我只需要将ItemsPresenter放在ScrollViewer中,而不是在ScrollViewer中使用DockPanel。因此,使用以下样式现在可以使用。

<Style TargetType="{x:Type c:TreeListView}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type c:TreeListView}">
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
               <DockPanel>
                  <GridViewHeaderRowPresenter DockPanel.Dock="Top" Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}" />
                  <ScrollViewer Focusable="False" Padding="{TemplateBinding Padding}">
                     <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                  </ScrollViewer>
               </DockPanel>
            </Border>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

非常感谢 Nikhil Agrawal 的代码!

4

2 回答 2

1

给出的解决方案是不完整的,只有在您有固定宽度控件时才有效。如果需要,仅包装ItemsPresenter标题列将不会水平滚动。这会导致移位的值列与标题不匹配。

我尝试过申请SelectiveScrollingGrid.SelectiveScrollingOrientation="Horizontal"GridViewHeaderRowPresenter但没有成功使用这种方法。

相反,您可以将滚动查看器添加到GridViewHeaderRowPresenterItemsPresenter,然后同步它们。这不是最好的解决方案,但至少它有效。

<Style TargetType="{x:Type local:TreeListView}">
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:TreeListView}">
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                <DockPanel>
                    <ScrollViewer DockPanel.Dock="Top"
                                  HorizontalScrollBarVisibility="Hidden"
                                  Name="scrollViewerHeader"
                                  VerticalScrollBarVisibility="Disabled">
                        <GridViewHeaderRowPresenter Columns="{StaticResource gvcc}"/>
                    </ScrollViewer>
                    <ScrollViewer HorizontalScrollBarVisibility="Auto"
                                  Name="scrollViewerBody"
                                  VerticalScrollBarVisibility="Auto">
                        <ItemsPresenter />
                    </ScrollViewer>
                </DockPanel>
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

以及背后的代码:

public class TreeListView : TreeView
{
    private ScrollViewer _scrollViewerHeader;
    private ScrollViewer _scrollViewerBody;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        _scrollViewerHeader = (ScrollViewer)Template.FindName("scrollViewerHeader", this);
        _scrollViewerBody = (ScrollViewer)Template.FindName("scrollViewerBody", this);

        _scrollViewerBody.ScrollChanged += (sender, e) =>
                                            {
                                                _scrollViewerHeader.Width = e.ViewportWidth;
                                                _scrollViewerHeader.ScrollToHorizontalOffset(e.HorizontalOffset);
                                            };
    }
}
于 2015-03-20T22:57:58.890 回答
0

DataGrid解决它的方法是自定义模板ScrollViewer以放置在GridViewHeaderRowPresenter外部ScrollViewer ScrollContentPresenter

https://github.com/dotnet/wpf/blob/059ba38771aef10d2172a3ca0e247dfbfa8cefde/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Aero2/Themes/Aero2.NormalColor.xaml#L987-L993

这样,当滚动条滚动时,它们不会影响标题行。

使用ListViewGridView这里做类似的事情: https ://github.com/dotnet/wpf/blob/059ba38771aef10d2172a3ca0e247dfbfa8cefde/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Aero2/Themes/Aero2.NormalColor.xaml#L2628

同时他们将标题行包装在另一个ScrollViewer中,老实说我不明白为什么。

一旦我发现更多,我将扩展这个答案。我认为这种方法如果有效的话比同步滚动查看器更干净。

于 2020-04-28T06:03:30.733 回答