Reputation: 3358
I have a Control
with a ScrollViewer
inside its ControlTemplate
(inside the Style
), I want to access that ScrollViewer
to work together with a ScrollSynchronizer
.
http://www.codeproject.com/Articles/39244/Scroll-Synchronization
Here's the Style
of the control:
<!--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>
I'm trying to do this:
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");
}
//...
}
I also tried to create a public Getter
inside the custom control:
public ScrollViewer GetScrollViewer()
{
return Template.FindName("ScrollViewer", this) as ScrollViewer;
}
This same code works when inside the OnApplyTemplate()
method. But on this case, Resources
is null or empty.
The ScrollSynchronization
class works while grouping ScrollViewer
elements using a AttachedProperty
:
<n:ZoomBox x:Name="ZoomBoxControl" util:ScrollSynchronizer.ScrollGroup="Group1"/>
<ScrollViewer x:Name="SideScrollViewer" util:ScrollSynchronizer.ScrollGroup="Group1"/>
So, the maybe the Zoombox
element is not even initialized before the OnScrollGroupChanged
fired. That may explain why the Resource
is always empty.
One possible solution may be set the AttachedProperty
after the window loading via code.
This code works, it runs at the Window_OnLoaded
event, I just wish I could use xaml to attach the properties.
ScrollSynchronizer.SetScrollGroup(ZoomBoxControl.GetScrollViewer(), "Canvas");
ScrollSynchronizer.SetScrollGroup(MainScrollViewer, "Canvas");
I looked at the Visual Tree after the OnGroupChanged
was called and it looks like the AttachedProperty
is resolved as soon as the ZoomBox
element is interpreted, but before its initialization. So there is no Template
loaded yet.
Upvotes: 0
Views: 72
Reputation: 8843
If I understand correctly you are writing a custom control, so you have a class somewhere deriving from Control
or a FrameworkElement
-derived class:
Just tested and this works perfectly for me:
[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;
}
}
As the MSDN article writes about OnApplyTemplate
:
Derived classes of FrameworkElement can use this method as a notification for a variety of possible scenarios:
- You can run code that relies on the visual tree from templates having been applied, such as obtaining references to named elements that came from a template.
Upvotes: 1