c# UWP TreeView 在 ItemDrag 上自动滚动

Posted

技术标签:

【中文标题】c# UWP TreeView 在 ItemDrag 上自动滚动【英文标题】:c# UWP TreeView autoscroll on ItemDrag 【发布时间】:2021-08-07 00:57:36 【问题描述】:

我面临一个非常简单且众所周知的问题。我的 UWP 应用程序中有一个树视图,用户可以通过拖放重新排序项目,但有一些限制。 d&d 本身就像预期的那样工作,但是现在,当我有一个很长的子项目列表要拖到树中非常高或低的地方时,我需要像每个用户从 Windows 资源管理器中知道的那样自动滚动,将光标向下移动到底部会激活滚动...但是...如何在 UWP 中实现它?我缺少任何默认属性吗?或者我什至如何滚动到树中的特定节点?有大量关于 Winform 甚至 WPF 的信息,但我卡在 UWP 上,无法将 WPF 解决方案转换为我的应用程序。

有人对这个问题有任何提示吗?

编辑:这是我的 XAML 的缩短版本:

<Page
    x:Class="CookBook.Views.EditCategoryPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:templateSelectors="using:CookBook.TemplateSelectors"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    xmlns:models="using:CookBook.Core.Models.Entities"
    xmlns:enums="using:CookBook.Core.Models"
    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    xmlns:behaviors="using:CookBook.Behaviors"
    xmlns:helpers="using:CookBook.Helpers"
    xmlns:interfaces="using:CookBook.Core.Models.Entities.Interfaces"
    xmlns:converters="using:CookBook.Helpers.Converter" xmlns:viewcontrols="using:CookBook.Views.ViewControls" xmlns:treeviewdata="using:CookBook.Models.TreeViewData"
    behaviors:NavigationViewHeaderBehavior.HeaderMode="Always"
    NavigationCacheMode="Disabled"
    Style="StaticResource PageStyle"
    mc:Ignorable="d">


    <Grid>
        <Grid>
            <Grid x:Name="mainGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition x:Name="treeViewColumn" Width="350"/>
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup>
                        <VisualState>
                            <VisualState.StateTriggers>
                                <!--641 is the default CompactModeThresholdWidth in NavigationView -->
                                <AdaptiveTrigger MinWindowWidth="641" />
                            </VisualState.StateTriggers>
                            <VisualState.Setters>
                                <Setter Target="header.Margin" Value="0,0,0,0" />
                                <Setter Target="treeViewColumn.Width" Value="350" />
                                <Setter Target="treeViewColumn.MaxWidth" Value="500" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Grid 
            Background="ThemeResource SystemChromeMediumLowColor">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="40" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid
                Margin="80,0,0,0"
                x:Name="header">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <TextBlock
                    x:Uid="TreeViewTitle"
                    Margin="StaticResource SmallLeftMargin"
                    Style="StaticResource ListTitleStyle"
                    VerticalAlignment="Center" />
                        <!--Fold all-->
                        <Button
                    Grid.Column="1"
                    x:Uid="TreeView_CollapseAllButton"
                    Content="&#xF165;"
                    FontSize="14"
                    Padding="StaticResource SmallLeftRightMargin"
                    VerticalAlignment="Stretch"
                    VerticalContentAlignment="Center"
                    FontFamily="Segoe MDL2 Assets"
                    Background="Transparent"
                    Click="OnCollapseAll" />
                        <!--expand all-->
                        <Button
                    Grid.Column="2"
                    x:Uid="TreeView_ExpandAllButton"
                    FontSize="14"
                    Padding="StaticResource SmallLeftRightMargin"
                    VerticalAlignment="Stretch"
                    VerticalContentAlignment="Center"
                    FontFamily="Segoe MDL2 Assets"
                    Background="Transparent"
                    Click="OnExpandAll" >
                            <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xEE47;"/>
                        </Button>
                        <!--Reorder Mode-->
                        <ToggleButton
                    Grid.Column="3"
                    Content="&#xE8FD;"
                    FontSize="14"
                    Padding="StaticResource SmallLeftRightMargin"
                    VerticalAlignment="Stretch"
                    VerticalContentAlignment="Center"
                    FontFamily="Segoe MDL2 Assets"
                    Background="Transparent"
                    IsThreeState="False"
                    RightTapped="ReorderModeRightClicked"
                    IsChecked="x:Bind ReorderMode, Mode=TwoWay" />
                        <!--Add-->
                        <Button
                    Grid.Column="4"
                    x:Name="foMenu"
                    x:Uid="Flyoutbutton"
                    Content="&#xE710;"
                    FontSize="14"
                    Padding="StaticResource SmallLeftRightMargin"
                    VerticalAlignment="Stretch"
                    VerticalContentAlignment="Center"
                    FontFamily="Segoe MDL2 Assets"
                    Background="Transparent">
                            <Button.Flyout>
                                <MenuFlyout>
                                    <MenuFlyoutItem Text="Neue Kategorie" Click="AddCategory" ></MenuFlyoutItem>
                                    <MenuFlyoutItem x:Name="btnCatIn" Text="x:Bind CategoryInText,Mode=OneWay" Click="AddCategory" />
                                    <MenuFlyoutSeparator />
                                    <MenuFlyoutItem x:Name="btnReceipeIn" Text="x:Bind ReceipeInText,Mode=OneWay" Click="AddReceipe" />
                                    <MenuFlyoutSeparator />
                                    <MenuFlyoutItem x:Name="btnImportFromCK" Text="Import aus Chefkoch" Click="BtnAddReceipeFromCK" />
                                    <MenuFlyoutSeparator />
                                    <MenuFlyoutItem x:Name="btnCBCut" Text="Ausschneiden" Click="CBCut" />
                                    <!--<MenuFlyoutItem  Text="Aus der Zwischenablage einfügen" Click="MoveReceipe" />-->
                                    <MenuFlyoutSubItem x:Name="btnCBAdd" Text="Einträge einfügen">
                                        
                                    </MenuFlyoutSubItem>
                                </MenuFlyout>
                            </Button.Flyout>
                        </Button>
                    </Grid>

                    <winui:TreeView
                BorderBrush="Beige"
                BorderThickness="1"
                x:Name="treeView"
                Grid.Row="1"
                SelectionMode="Single"
                
                CanBeScrollAnchor="True"
                        
                ItemsSource="x:Bind CategoryItems,Mode=TwoWay"
                ItemInvoked="OnItemInvoked"
                ItemTemplateSelector="StaticResource TreeViewTemplateSelector"
                
                
                DragItemsStarting="TreeView_DragItemsStarting"
                DragItemsCompleted="TreeView_DragItemsCompleted"
                
                Width="auto">
                        <winui:TreeView.ItemContainerStyle>
                            <Style TargetType="winui:TreeViewItem">
                                <Setter Property="VerticalAlignment" Value="Stretch" />
                                <Setter Property="VerticalContentAlignment" Value="Stretch" />
                            </Style>
                        </winui:TreeView.ItemContainerStyle>
                    </winui:TreeView>
                </Grid>

                <ScrollViewer
            Grid.Column="1" >
                    <ContentControl
                Content="x:Bind SelectedItem, Mode=OneWay"
                ContentTemplateSelector="StaticResource ContentTemplateSelector"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                VerticalContentAlignment="Stretch"
                HorizontalContentAlignment="Stretch" />
                </ScrollViewer>

                <controls:GridSplitter
            Grid.Column="1"
            GripperCursor="Default"
            HorizontalAlignment="Left"
            ResizeDirection="Auto"
            ResizeBehavior="BasedOnAlignment"
            CursorBehavior="ChangeOnSplitterHover"
            Width="16" />
            </Grid>

            <ScrollViewer x:Name="sViewerSingle" Visibility="Collapsed">
                <ContentControl
                Content="x:Bind SelectedItem, Mode=TwoWay"
                ContentTemplateSelector="StaticResource ContentTemplateSelector"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                VerticalContentAlignment="Stretch"
                HorizontalContentAlignment="Stretch" />
            </ScrollViewer>
        </Grid>
    </Grid>
</Page>

【问题讨论】:

你能分享你写的代码吗?你的意思是在放置完成时自动滚动到顶部还是底部? @NicoZhu-MSFT phu....也许我可以隔离我的 sn-p 并制作一个演示应用程序,否则我们将有很大的代码过载。但在以前:我的意思是在拖动时自动滚动,而不是在放置时。请在 Windows 资源管理器中测试此行为,将文件从目录列表的最顶部拖到最末尾,当光标碰到底部边框时,资源管理器将向下滚动 您可以参考这个案例reply。 是的,试过了,我在获取合适的父级时遇到了问题……我制作了一个小型示例存储库。您可以拖放每个组中的每一片叶子,但如何实现这种滚动行为:github.com/tzdlr/TreeViewReorderSample 我测试了你的代码,发现你的treeview不能正常滚动,请使用Grid替换默认的StackPanel作为treeview的父级,然后再次尝试拖动项目,你会发现结果。 【参考方案1】:

c# UWP TreeView 在 ItemDrag 上自动滚动

TreeView 包含向下或向上拖动项目时的滚动行为。 在检查您的 xaml 代码期间,ScrollViewer 覆盖 TreeWiew,它将影响 TreeView 并防止滚动行为。请尝试将其移至其他区域。

【讨论】:

你是对的,我的 xaml 中有一个加倍...。一个滚动查看器已折叠,但似乎覆盖了整个页面并阻止滚动!感谢您指出!删除 查看器后,它就像一个魅力!

以上是关于c# UWP TreeView 在 ItemDrag 上自动滚动的主要内容,如果未能解决你的问题,请参考以下文章

在UWP应用程序中使用TreeView时如何处理命名空间冲突

UWP解析Windows.Storage.StorageFolder并添加TreeView

UWP - Flyout中的WinRT xaml工具包TreeView,在弹出窗口关闭后更改选择

wpf中的treeview如何增加2级节点?在C#中如何添加?

怎样在treeview中加载数据库 C#

c# treeview在指定名称下添加节点!怎么做?