3

我认为这应该很容易,但我遇到了困难。

如何在 C# 中获取对 ListBox 的滚动查看器的引用?我已经尝试了几乎所有我能想到的东西。ListBox 位于 WPF 自定义控件中,因此我们使用 Template.FindName 来获取对所有控件的引用。我的列表框看起来像这样:

<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 结果为空。

有任何想法吗?

4

6 回答 6

5

您可能试图过早获得对 ScrollViewer 的引用。尝试在加载的事件中移动代码并检查它是否仍然返回 null:

在您的 customControl/form 构造函数中:

this.Loaded += MainWindow_Loaded;

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
   var x = PART_SoundList.Template.FindName("Scroller", PART_SoundList);
}
于 2010-10-18T21:36:41.743 回答
2

我假设您上面的 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;
    }
}
于 2010-10-18T21:33:17.823 回答
1

使用对 Visual Tree 的递归调用从树中获取任何 Visual。

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 元素。

于 2010-10-18T21:04:12.397 回答
1

对于那些来到这里寻求原始问题答案的人:

在 C# 中

ScrollViewer sv = FindVisualChild<ScrollViewer>(MyListBox);

或在 VB 中

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

XAML 中的位置

<ListBox x:Name="MyListBox">
</ListBox>
于 2016-05-26T08:05:15.840 回答
0

如果您要使用引用来滚动/检查视口大小,则IScrollProvider对您来说应该足够了。

您可以在后面的代码中像这样访问它(注意等待加载事件的 Claudiu 点):

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

然后随时随地水平和垂直滚动,随心所欲。

于 2010-10-18T22:10:43.477 回答
0

使用它来访问 WPF 中的滚动查看器。

var scrollViewer = ((Border)PlaybackDeviceList.Template.FindName("Bd", PlaybackDeviceList)).Child;

于 2018-07-04T11:55:05.893 回答