Where would the human race be without thumbs?
Thumb is not only a component of the Slider
template: It can also be used as a general-purpose manipulable control
for dragging with your finger around the screen. The problem is this:
With its default template, the Thumb is ugly enough to be considered “unusable.” It really needs a custom template.
Thumb derives from Control, defines an IsDragging method, and three events: DragStarted, DragDelta, and DragCompleted. A CancelDrag method lets you abort the process midway through.
The most important event is DragDelta, which comes with event arguments named HorizontalChange and VerticalChange, so you can think of the Thumb as a high-level interface to the Manipulation events—or at least when you’re working solely with translation.
Here’s the content area of the ThumbBezier program.
Example 1. Silverlight Project: ThumbBezier File: MainPage.xaml (excerpt)
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Path Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="2"> <Path.Data> <PathGeometry> <PathFigure x:Name="pathFig" StartPoint="100 100"> <BezierSegment x:Name="pathSeg" Point1="300 100" Point2="300 400" Point3="100 400" /> </PathFigure> </PathGeometry> </Path.Data> </Path>
<Polyline Name="ctrl1Line" Stroke="{StaticResource PhoneForegroundBrush}" StrokeDashArray="2 2" Points="100 100, 300 100" />
<Polyline Name="ctrl2Line" Stroke="{StaticResource PhoneForegroundBrush}" StrokeDashArray="2 2" Points="300 400, 100 400" />
<Thumb Name="pt0Thumb" Style="{StaticResource thumbStyle}" DragDelta="OnThumbDragDelta"> <Thumb.RenderTransform> <TranslateTransform X="100" Y="100" /> </Thumb.RenderTransform> </Thumb>
<Thumb Name="pt1Thumb" Style="{StaticResource thumbStyle}" DragDelta="OnThumbDragDelta"> <Thumb.RenderTransform> <TranslateTransform X="300" Y="100" /> </Thumb.RenderTransform> </Thumb>
<Thumb Name="pt2Thumb" Style="{StaticResource thumbStyle}" DragDelta="OnThumbDragDelta"> <Thumb.RenderTransform> <TranslateTransform X="300" Y="400" /> </Thumb.RenderTransform> </Thumb>
<Thumb Name="pt3Thumb" Style="{StaticResource thumbStyle}" DragDelta="OnThumbDragDelta"> <Thumb.RenderTransform> <TranslateTransform X="100" Y="400" /> </Thumb.RenderTransform> </Thumb> </Grid>
|
All four Thumb controls share the same DragDelta event handler, which is pretty much the only responsibility of the code-behind file. You’ll need a using directive for the System.Windows.Control.Primitives namespace for the Thumb and its event arguments.
Example 2. Silverlight Project: ThumbBezier File: MainPage.xaml.cs (excerpt)
void OnThumbDragDelta(object sender, DragDeltaEventArgs args) { Thumb thumb = sender as Thumb; TranslateTransform translate = thumb.RenderTransform as TranslateTransform; translate.X += args.HorizontalChange; translate.Y += args.VerticalChange;
if (thumb == pt0Thumb) { pathFig.StartPoint = Move(pathFig.StartPoint, args.HorizontalChange, args.VerticalChange); ctrl1Line.Points[0] = Move(ctrl1Line.Points[0], args.HorizontalChange, args.VerticalChange); } else if (thumb == pt1Thumb) { pathSeg.Point1 = Move(pathSeg.Point1, args.HorizontalChange, args.VerticalChange); ctrl1Line.Points[1] = Move(ctrl1Line.Points[1], args.HorizontalChange, args.VerticalChange); } else if (thumb == pt2Thumb) { pathSeg.Point2 = Move(pathSeg.Point2, args.HorizontalChange, args.VerticalChange); ctrl2Line.Points[0] = Move(ctrl2Line.Points[0], args.HorizontalChange, args.VerticalChange); } else if (thumb == pt3Thumb) { pathSeg.Point3 = Move(pathSeg.Point3, args.HorizontalChange, args.VerticalChange); ctrl2Line.Points[1] = Move(ctrl2Line.Points[1], args.HorizontalChange, args.VerticalChange); } }
Point Move(Point point, double horzChange, double vertChange) { return new Point(point.X + horzChange, point.Y + vertChange); }
|
In a Style and ControlTemplate defined in the Resources collection, the Thumb is given an appearance much like the translucent round elements I used in the earlier program. The only visual element of the ControlTemplate is a Path with an EllipseGeometry:
Example 3. Silverlight Project: ThumbBezier File: MainPage.xaml (excerpt)
<phone:PhoneApplicationPage.Resources> <Style x:Key="thumbStyle" TargetType="Thumb"> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Thumb">
<Path Name="path" Fill="{StaticResource PhoneAccentBrush}" Opacity="0.5"> <Path.RenderTransform> <ScaleTransform x:Name="scale" /> </Path.RenderTransform>
<Path.Data> <EllipseGeometry x:Name="ellipseGeometry" RadiusX="48" RadiusY="48" /> </Path.Data>
<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"> <Storyboard> <DoubleAnimation Storyboard.TargetName="path" Storyboard.TargetProperty="Opacity" Duration="0:0:0.25" /> <DoubleAnimation Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleX" Duration="0:0:0.25" /> <DoubleAnimation Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleY" Duration="0:0:0.25" />
</Storyboard> </VisualState>
<VisualState x:Name="MouseOver" /> <VisualState x:Name="Disabled" />
<VisualState x:Name="Pressed"> <Storyboard> <DoubleAnimation Storyboard.TargetName="path" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0:0:0.25" /> <DoubleAnimation Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleX" To="1.25" Duration="0:0:0.25" /> <DoubleAnimation Storyboard.TargetName="scale" Storyboard.TargetProperty="ScaleY" To="1.25" Duration="0:0:0.25" /> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Path> </ControlTemplate> </Setter.Value> </Setter> </Style> </phone:PhoneApplicationPage.Resources>
|
The Thumb has a Pressed visual state, so this suggests that a feature can be added not present in the earlier programs: The Thumb can indicate that it’s pressed
and being dragged by growing a bit and by changing color. A few
animations are all that’s necessary to add this feature to the template.