是否获取对WPF列表框的滚动查看器的引用?

klsxnrf1  于 2023-03-04  发布在  其他
关注(0)|答案(5)|浏览(140)

如何在C#中获得对ListBoxScrollViewer的引用?我几乎尝试了所有我能想到的方法。ListBox位于WPF自定义控件中,因此我们使用Template.FindName来获得对所有控件的引用。我的ListBox如下所示:

<ListBox
 x:Name="PART_SoundList" 
 ScrollViewer.CanContentScroll="False" 
 ScrollViewer.HorizontalScrollBarVisibility="Auto"  
 ScrollViewer.VerticalScrollBarVisibility="Hidden"
 Focusable="False"
 FocusVisualStyle="{x:Null}"
 HorizontalAlignment="Center"
 VerticalAlignment="Bottom"
 BorderThickness="0" 
 ItemContainerStyleSelector="{StaticResource ListBoxItemAlternatingStyleSelector}"
 ItemsSource="{Binding}">

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Vertical" Height="850" Focusable="False" Panel.ZIndex="999"  >
                <WrapPanel.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform CenterX="0" CenterY="0" ScaleX=".75" ScaleY=".57" />
                        </TransformGroup>
                    </WrapPanel.RenderTransform>
            </WrapPanel>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    <ListBox.Template>
        <ControlTemplate>
            <ScrollViewer x:Name="Scroller" VerticalAlignment="Bottom" Focusable="False" Style="{StaticResource HorizontalScroller}"   >
                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Focusable="False" Panel.ZIndex="999"  />
            </ScrollViewer>
        </ControlTemplate>
    </ListBox.Template>

</ListBox>

Template.FindName("Scroller", this) as ScrollViewer的结果是null
有什么想法吗?

ilmyapht

ilmyapht1#

您可能尝试过早获取对ScrollViewer的引用。尝试在加载的事件中移动代码并检查它是否仍返回null:
在customControl/窗体构造函数中:

this.Loaded += MainWindow_Loaded;

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
   var x = PART_SoundList.Template.FindName("Scroller", PART_SoundList);
}
x7yiwoj4

x7yiwoj42#

我假设上面的XAML是CustomControl的ControlTemplate的一部分,对吗?我还假设您正在OnApplyTemplate()方法上获取控件部分,对吗?如果是这种情况,那么,我认为您需要做的是在找到ScrollViewer之前强制调用PART_SoundList.ApplyTemplate()。因此,自定义控件的代码应该如下所示:

public class MyControl : Control
{
    private ListBox lb;
    private ScrollViewer scroller;

    static MyControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
    }

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

        lb = this.Template.FindName("PART_SoundList", this) as ListBox;
        lb.ApplyTemplate();
        scroller = lb.Template.FindName("Scroller", lb) as ScrollViewer;
    }
}
mxg2im7a

mxg2im7a3#

对于那些来到这里寻求最初问题答案的人:
在C#中

ScrollViewer sv = FindVisualChild<ScrollViewer>(MyListBox);

或在VB中

Dim sv As ScrollViewer = FindVisualChild(Of ScrollViewer)(MyListBox)

XAML中的位置

<ListBox x:Name="MyListBox">
</ListBox>
smdncfj3

smdncfj34#

使用对可视化树的递归调用从树中获取任何可视化对象。

public static ChildItem FindVisualChild<childItem>(DependencyObject obj) where ChildItem : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is ChildItem)
            return (ChildItem)child;
        else
        {
            ChildItem childOfChild = FindVisualChild<ChildItem>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}

这为您提供了一个从Visual树中获取所提及类型的Visual元素的通用方法。

yrdbyhpb

yrdbyhpb5#

如果您打算使用参考滚动/检查视口大小,IScrollProvider应该足够了。
您可以在代码中像这样访问它(注意Claudiu等待加载事件的点):

ListBoxAutomationPeer svAutomation = (ListBoxAutomationPeer)ScrollViewerAutomationPeer.CreatePeerForElement(PART_SoundList);
// not feeling creative with my var names today...
IScrollProvider scrollInterface = (IScrollProvider)svAutomation.GetPattern(PatternInterface.Scroll);

然后水平和垂直滚动,只要你想和你的心的内容。

相关问题