BubbleControl
A content control that answers every click on its content with a ripple: a ring of colour that spreads out from the point clicked and fades away, as a touch screen shows where it was touched.
public class BubbleControl : ContentControl
Inherits from / implements: ContentControl
Remarks
Wrap it round anything – a button, a tile, an image, a whole panel – to give the user an immediate, visible answer to a click. It is especially useful on touch screens and kiosks, in software demonstrations and screen recordings, where the audience needs to see where the presenter clicked, and on large tiles whose own response might otherwise go unnoticed.
How it works
A press of the left mouse button anywhere over the content starts a bubble at the pointer.
The bubble grows over 0.55 seconds to a diameter of BubbleExpansionFactor times
twice the control's longer side, fading out as it grows, and is clipped to the control's bounds. The
click still reaches the content as normal – the control only watches it.
Appearance
The bubble is three concentric rings: BubbleOuterLayerBrush on the outside,
BubbleInnerLayerBrush at half the diameter and BubbleChildLayerBrush at
a quarter. ShouldRunOnTop chooses whether it is drawn over the content or behind it.
The default style gives the control a transparent Control.Background, so the whole of
its area answers the pointer, not only the parts the content paints.
Which gestures raise a bubble
Add other routed events – a right-button release, a touch, a stylus tap – to
BubbleInvocationEvents. Events that carry a pointer position start the bubble there.
Examples
A grid of dashboard tiles, each wrapped so that a click or a right-click ripples in the company's colours.
<Window x:Class="Dashboard.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cv="clr-namespace:Binarymission.WPF.Controls.CommandVisuals;assembly=Binarymission.WPF.Controls.BubbleControl"
Title="Sales dashboard" Width="640" Height="360">
<UniformGrid Columns="2" Margin="12">
<cv:BubbleControl BubbleExpansionFactor="0.3"
BubbleOuterLayerBrush="#552196F3"
BubbleInnerLayerBrush="#882196F3"
BubbleChildLayerBrush="#FF1565C0">
<Border Margin="6" Background="#F3F7FC" BorderBrush="#C9D6E6" BorderThickness="1"
MouseLeftButtonUp="OnOpenOrders">
<TextBlock Margin="16" FontSize="18" Text="Open orders: 128" />
</Border>
</cv:BubbleControl>
<cv:BubbleControl BubbleExpansionFactor="0.3">
<Border Margin="6" Background="#F3F7FC" BorderBrush="#C9D6E6" BorderThickness="1">
<TextBlock Margin="16" FontSize="18" Text="Overdue invoices: 7" />
</Border>
</cv:BubbleControl>
</UniformGrid>
</Window>The same in code, with the right mouse button raising a bubble too.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Binarymission.WPF.Controls.CommandVisuals;
BubbleControl tile = new BubbleControl
{
BubbleExpansionFactor = 0.3,
BubbleOuterLayerBrush = new SolidColorBrush(Color.FromArgb(0x55, 0x21, 0x96, 0xF3)),
Content = new TextBlock { Margin = new Thickness(16), FontSize = 18, Text = "Open orders: 128" }
};
tile.BubbleInvocationEvents.Add(UIElement.MouseRightButtonUpEvent);See also
Members at a glance
| Constructors | |
|---|---|
BubbleControl | Creates a bubble control that answers the left mouse button, with its own
BubbleInvocationEvents collection. |
| Properties | |
BubbleChildLayerBrush | Gets or sets the colour of the dot at the centre of the bubble, a quarter of the diameter of the outer ring. |
BubbleExpansionFactor | Gets or sets how large the bubble grows, as a proportion of the control's size. |
BubbleInnerLayerBrush | Gets or sets the colour of the bubble's middle ring, half the diameter of the outer one. |
BubbleInvocationEvents | Gets or sets the routed events, besides a press of the left mouse button, that start a bubble. |
BubbleOuterLayerBrush | Gets or sets the colour of the bubble's outer ring – the widest part of the ripple. |
ShouldRunOnTop | Gets or sets whether the bubble is drawn over the content or behind it. |
| Methods | |
OnApplyTemplate | Finds the parts of the template that draw the bubble, and starts listening for the left mouse button. |
| Fields | |
BubbleChildLayerBrushProperty | Identifies the BubbleChildLayerBrush dependency property. |
BubbleExpansionFactorProperty | Identifies the BubbleExpansionFactor dependency property. |
BubbleInnerLayerBrushProperty | Identifies the BubbleInnerLayerBrush dependency property. |
BubbleInvocationEventsProperty | Identifies the BubbleInvocationEvents dependency property. |
BubbleOuterLayerBrushProperty | Identifies the BubbleOuterLayerBrush dependency property. |
ShouldRunOnTopProperty | Identifies the ShouldRunOnTop dependency property. |
Constructors
BubbleControl
Creates a bubble control that answers the left mouse button, with its own
BubbleInvocationEvents collection.
Properties
BubbleChildLayerBrush
Gets or sets the colour of the dot at the centre of the bubble, a quarter of the diameter of the outer ring.
- Value
- The default is
Brushes.DarkSeaGreen.
See also
BubbleExpansionFactor
Gets or sets how large the bubble grows, as a proportion of the control's size.
- Value
- The bubble's final diameter is this value times twice the longer of the control's actual
width and height. The default is
0.14: on a control 200 logical pixels wide the bubble grows to 56 logical pixels.
Remarks
0 turns the bubble off. 0.5 grows it to the control's longer side, which on a
square control is enough to cover it; larger values spread past the edges, where the bubble is
clipped. The size is worked out at each click, so it follows the control as it is resized.
Example
<!-- A wide, gentle ripple for a large touch tile. -->
<cv:BubbleControl BubbleExpansionFactor="0.4" />BubbleInnerLayerBrush
Gets or sets the colour of the bubble's middle ring, half the diameter of the outer one.
- Value
- The default is
Brushes.LightSalmon.
See also
BubbleInvocationEvents
Gets or sets the routed events, besides a press of the left mouse button, that start a bubble.
- Value
- A collection of routed events. Each control starts with a collection of its own holding
UIElement.MouseLeftButtonDownEvent.
Remarks
Add any routed event raised on or inside the control – for example
UIElement.MouseRightButtonUpEvent, UIElement.TouchDownEvent or
UIElement.StylusDownEvent. The control listens for it even when the content has
already handled it. Events added to or removed from the collection take effect at once, and so does
replacing the whole collection; null leaves only the left button.
The left mouse button always starts a bubble: removing
UIElement.MouseLeftButtonDownEvent from the collection does not turn it off. Set
BubbleExpansionFactor to 0 to stop bubbles altogether.
A mouse button event starts the bubble at the pointer. Any other event replays it at the place, and the size, of the last mouse button press; before the first press it shows nothing.
Example
// Ripple on a right-click as well, for a context-menu tile.
tile.BubbleInvocationEvents.Add(UIElement.MouseRightButtonUpEvent);BubbleOuterLayerBrush
Gets or sets the colour of the bubble's outer ring – the widest part of the ripple.
- Value
- The default is
Brushes.LightGreen.
Remarks
The whole bubble fades out as it grows, so opaque colours work well; with
ShouldRunOnTop on, a partly transparent colour lets the content show through even
at the start.
See also
ShouldRunOnTop
Gets or sets whether the bubble is drawn over the content or behind it.
- Value
trueto draw the bubble over the content, where it is always seen;falseto draw it behind, where it shows only through the parts of the content that are transparent. The default style setstrue; the value registered on the property isfalse.
Remarks
Drawing behind suits content with an open background, such as text or an icon on a transparent tile: the ripple spreads round the text without covering it. Over an opaque background it cannot be seen at all. The value is read at each click, so a change takes effect at the next one.
Methods
OnApplyTemplate
Finds the parts of the template that draw the bubble, and starts listening for the left mouse button.
Remarks
A custom template gives the bubble a Grid named PART_BubbleLayersHost
holding a Storyboard resource keyed StoryPlayer, and a Border
named PART_BubbleTopLayer for the bubble itself. Every part is optional: a template without
them still shows its content and simply draws no bubble.
Fields
BubbleChildLayerBrushProperty static
Identifies the BubbleChildLayerBrush dependency property.
BubbleExpansionFactorProperty static
Identifies the BubbleExpansionFactor dependency property.
BubbleInnerLayerBrushProperty static
Identifies the BubbleInnerLayerBrush dependency property.
BubbleInvocationEventsProperty static
Identifies the BubbleInvocationEvents dependency property.
BubbleOuterLayerBrushProperty static
Identifies the BubbleOuterLayerBrush dependency property.
ShouldRunOnTopProperty static
Identifies the ShouldRunOnTop dependency property.