views:

496

answers:

2

I have a custom control containing a path that has a templated tooltip. I want to be able to get a reference to a grid in the template at runtime so that I can modify it's children depending on use.

I thought I could use GetTemplateChild to get a reference to the grid in the template from within the OnApplyTemplate method of the control but this method is not firing.

public override void OnApplyTemplate()
{
  base.OnApplyTemplate();

  _tooltipDetails = (Grid)GetTemplateChild("TooltipDetailsGrid");
}

How else might I be able to do this?

Here is the user control's XAML.

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="MiX.AssetManagement.UI.Timeline.Silverlight.TimelineBarRibbonItem"
    FontSize="9.333" Foreground="White" mc:Ignorable="d">
    <UserControl.Resources>
     <ControlTemplate x:Key="ToolTipControlTemplateTimelineView" TargetType="ToolTip">
      <StackPanel Orientation="Horizontal" Margin="16,0,0,0">
       <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="OpenStates">
         <VisualState x:Name="Closed"/>
         <VisualState x:Name="Open"/>
        </VisualStateGroup>
       </VisualStateManager.VisualStateGroups>
       <Border CornerRadius="4">
        <Border.Background>
         <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
          <GradientStop Color="#7F000000" Offset="0"/>
          <GradientStop Color="#B2000000" Offset="1"/>
         </LinearGradientBrush>
        </Border.Background>
        <Grid Margin="4">
         <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
         </Grid.ColumnDefinitions>
         <Border x:Name="Info" Height="16" Width="16" BorderThickness="2" CornerRadius="8" HorizontalAlignment="Left" VerticalAlignment="Top">
          <Border.BorderBrush>
           <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="White" Offset="0"/>
            <GradientStop Color="#7FFFFFFF" Offset="1"/>
           </LinearGradientBrush>
          </Border.BorderBrush>
          <Path Fill="White" Stretch="Fill" Margin="5.229,2.089,5.035,2.82" RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False" Data="M0.77471197,5.0623446 L2.4198356,5.0623446 L2.4198356,10.18 L0.77471197,10.18 z M0.72914064,3.0891075 L2.4654069,3.0891075 L2.4654069,4.3332038 L0.72914064,4.3332038 z">
           <Path.RenderTransform>
            <TransformGroup>
             <ScaleTransform/>
             <SkewTransform/>
             <RotateTransform/>
             <TranslateTransform/>
            </TransformGroup>
           </Path.RenderTransform>
          </Path>
         </Border>
         <ContentPresenter d:LayoutOverrides="Width, Height" Margin="20,0,0,0"/>
         <Grid Grid.Column="1" x:Name="TooltipDetailsGrid">
          <TextBlock Text="Tooltip in a Grid"/>
         </Grid>
        </Grid>
       </Border>
      </StackPanel>
     </ControlTemplate>
    </UserControl.Resources>

    <Path x:Name="RibbonItem" Cursor="Hand">
     <Path.Fill>
      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
       <GradientStop Color="#FF66CC33"/>
       <GradientStop Color="#FF339900" Offset="1"/>
      </LinearGradientBrush>
     </Path.Fill>
     <ToolTipService.ToolTip>
      <ToolTip x:Name="RibbonItemTooltip" Content="" Foreground="#FFFFFFFF" FontSize="9.333" Placement="Mouse" Template="{StaticResource ToolTipControlTemplateTimelineView}"/>
     </ToolTipService.ToolTip>
     <Path.Data>
      <GeometryGroup x:Name="RibbonItemGeometryGroup">
       <RectangleGeometry x:Name="RibbonItemBackground" />
      </GeometryGroup>
     </Path.Data>
    </Path>
</UserControl>
+1  A: 

You need to be handling code in the ToolTip Classes OnApplyTemplate method. Here is my untested stab at what you need to do:-

Inherit from ToolTip and override the OnApplyTemplate method in this new class:-

 public MyToolTip : ToolTip
 {
     public override void OnApplyTemplate()
     {
         //Perhaps to stuff
         base.OnApplyTemplate();
         //Perhaps to other stuff
     }
 }

In your resources you now set the TargetType to local:MyToolTip and ensure your assembly namespace is placed with the local alias in the user control element.

Now in your Xaml:-

    <ToolTipService.ToolTip>
            <local:MyToolTip x:Name="RibbonItemTooltip" Content="" Foreground="#FFFFFFFF" FontSize="9.333" Placement="Mouse" Template="{StaticResource ToolTipControlTemplateTimelineView}"/>
    </ToolTipService.ToolTip>
AnthonyWJones
A: 

I have resolved this in a slightly different way. Rather than modify the template at runtime I have created an instance of the template for each use case. I can then apply the correct template when I create the instance and elements in the template bind to control class to populate the tooltip with the appropriate values.

This is probably a better approach as the structure of the tooltips is now clearly visible in the XAML, rather than being hidden away in the code.

Steve Crane