我认为这应该很容易,但我很难接受它。
如何在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。
有什么想法吗?
答案 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;