在C#中引用我的WPF ListBox的ScrollViewer?

时间:2010-10-18 20:59:20

标签: wpf listbox scrollview

我认为这应该很容易,但我很难接受它。

如何在C#中获取对ListBox的scrollviewer的引用?我已经尝试了几乎所有我能想到的东西。 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),因为ScrollViewer导致null。

有什么想法吗?

6 个答案:

答案 0 :(得分:5)

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

你的customControl /表单构造函数中的

this.Loaded += MainWindow_Loaded;

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

答案 1 :(得分:2)

使用对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元素。

答案 2 :(得分: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;
    }
}

答案 3 :(得分: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);

然后随时随地水平和垂直滚动。

答案 4 :(得分:0)

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

在C#中

ScrollViewer sv = FindVisualChild<ScrollViewer>(MyListBox);

或在VB中

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

XAML中的位置

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

答案 5 :(得分:0)

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

var scrollViewer =(((Border)PlaybackDeviceList.Template.FindName(“ Bd”,PlaybackDeviceList))。Child;