如何访问元素的模板

本文关键字:元素 访问 何访问 | 更新日期: 2023-09-27 18:36:01

我有一个Control,它的ControlTemplate内(Style内)有一个ScrollViewer,我想访问该ScrollViewerScrollSynchronizer一起工作。

http://www.codeproject.com/Articles/39244/Scroll-Synchronization

下面是控件的Style

<!--ZoomControl-->
<Style TargetType="{x:Type local:ZoomBox}">
    <Setter Property="ClipToBounds" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ZoomBox}">
                <ScrollViewer x:Name="ScrollViewer" ClipToBounds="True"
                              Background="Transparent" SnapsToDevicePixels="True" 
                              UseLayoutRounding="True"
                              VerticalScrollBarVisibility="Auto" 
                              HorizontalScrollBarVisibility="Auto" >
                    <Grid x:Name="Grid" RenderTransformOrigin="0.5,0.5" 
                          Background="Transparent" HorizontalAlignment="Center" 
                          VerticalAlignment="Center" SnapsToDevicePixels="True" 
                          UseLayoutRounding="True">
                        <Grid.LayoutTransform>
                            <TransformGroup>
                                <ScaleTransform x:Name="ScaleTransform"/>
                            </TransformGroup>
                        </Grid.LayoutTransform>
                        <Viewbox Grid.Column="0" Grid.Row="0" SnapsToDevicePixels="True" 
                                 UseLayoutRounding="True">
                            <Image Name="ImageCtrl" Source="{TemplateBinding ImageSource, 
                                   Converter={StaticResource UriToBitmapConverter}}" 
                                   SnapsToDevicePixels="True" UseLayoutRounding="True"/>
                        </Viewbox>
                    </Grid>
                </ScrollViewer>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我正在尝试这样做:

private static void OnScrollGroupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var scrollViewer = d as ScrollViewer;
    if (scrollViewer == null && d.GetType() == typeof (ZoomBox))
    {
        //FindResource always returns null.
        scrollViewer = (ScrollViewer)(d as ZoomBox).FindResource("ScrollViewer");
    }
    //...
}

我还尝试在自定义控件中创建一个公共Getter

public ScrollViewer GetScrollViewer()
{
    return Template.FindName("ScrollViewer", this) as ScrollViewer;
}

OnApplyTemplate() 方法中,相同的代码有效。但在这种情况下,Resources为空或为空。

编辑:

ScrollSynchronization类在使用AttachedProperty对元素进行分组ScrollViewer时工作:

<n:ZoomBox x:Name="ZoomBoxControl" util:ScrollSynchronizer.ScrollGroup="Group1"/>
<ScrollViewer x:Name="SideScrollViewer" util:ScrollSynchronizer.ScrollGroup="Group1"/>

因此,在触发OnScrollGroupChanged之前,Zoombox元素甚至没有初始化。这也许可以解释为什么Resource总是空的。

编辑 2:

一种可能的解决方案是在窗口加载后通过代码设置AttachedProperty

编辑3:

这段代码有效,它在 Window_OnLoaded 事件中运行,我只是希望我可以使用 xaml 来附加属性。

ScrollSynchronizer.SetScrollGroup(ZoomBoxControl.GetScrollViewer(), "Canvas");
ScrollSynchronizer.SetScrollGroup(MainScrollViewer, "Canvas");

在调用OnGroupChanged后,我查看了可视化树,看起来AttachedProperty在解释ZoomBox元素后立即解决,但在初始化之前。所以还没有加载Template

如何访问元素的模板

如果我

理解正确,您正在编写一个自定义控件,因此您在某处有一个派生自ControlFrameworkElement派生类的类:

刚刚测试过,这对我来说非常有效:

[TemplatePart(Name = "ScrollViewer", Type = typeof(ScrollViewer))]
public class ZoomBox : Control
{
    private ScrollViewer _scrollViewerPart;
    public override void OnApplyTemplate()
    {
        _scrollViewerPart = GetTemplateChild("ScrollViewer") as ScrollViewer;
    }
    public ScrollViewer GetScrollViewer()
    {
        return _scrollViewerPart;
    }
}

正如 MSDN 文章所写的关于OnApplyTemplate

FrameworkElement 的派生类可以使用此方法作为各种可能方案的通知:

  • 可以运行依赖于已应用模板中的可视化树的代码,例如获取对来自模板的命名元素的引用。