In our blog post
Introducing Annotations, we looked into the different ways of
creating and deleting annotations from the chart and how we can
interact with them. In this blog post, we will take a closer look
at how we can style annotations. Annotations are only available in
the premium version of
Visiblox charts.
Annotation Elements
Each annotation consists of an
AnnotationElement and a
MovingElement. The AnnotationElement is what we
see when we are not interacting with the annotation - the normal
element - whereas the MovingElement is an extra element rendered on
top of the AnnotationElement when we are interacting with the
annotation (dragging/editing/clicking etc). For example, the
MovingElement of the LineAnnotation is a much thicker,
semi-transparent line which makes clicking the annotation easier.
In most of the predefined annotations, the AnnotationElement and
the MovingElement have the same shape but a different style. Some
examples are displayed below:

normal & interacting line annotation

normal & interacting text annotation

normal & interacting callout text annotation
Element Styles
Both the AnnotationElement and the MovingElement have different
styles applied to them depending on the state in which the
annotation is in. The possible states are: normal
(no interaction), selected,
highlighted/moving and
creationand the element styles are:
- AnnotationElementStyle: the style applied to
the AnnotationElement when the annotation is at the normal
state.
- AnnotationElementSelectedStyle: the style
applied to the AnnotationElement when the annotation is
selected.
- AnnotationElementCreationStyle: the style
applied to the AnnotationElement when the annotation is being
created. This style is only useful when creating annotations using
the AnnotationBehaviour, not when the annotations are added
programmatically.
- MovingElementStyle: the style applied to the
MovingElement when the annotation is highlighted or moving.
- MovingElementCollapsedStyle: the style applied
to the MovingElement when no interaction takes place or when the
annotation is in either the normal, selected and creation state.
Typically, it will either be collapsed or invisible.
Applying Custom Styles
Now that we've taken a bit of a closer look at the elements and
their styles, we will look into the different ways we can apply a
custom style. We can either create a custom style
for one of the element styles discussed above or create a
complete annotation style - provide a custom style
for all of the element styles. The custom style creation can either
be done from code or from xaml.
If you want your custom style to be applied to all the annotations
of the same type, you can create an implicit
style. In the following sections we will explore each of
the options separately, but first let's look at how we select the
target type of each style.
Selecting the TargetType
As we already mentioned, the AnnotationElement is the visual
element normally displayed and the MovingElement is usually the
same type of element displayed on top of the AnnotationElement. The
more complex annotations, like the CalloutTextAnnotation, have a
different TargetType for the AnnotationElement and the
MovingElement. Here is a list for all the predefined
annotations:
- Line, HorizontalLine, HorizontalLineWithValue,
VerticalLine, VerticalLineWithValue: the TargetType for
all the element styles is Line.
- Rectangle, Ellipse: the TargetType is
Shape.
- EventAnnotation: the TargetType is
EventAnnotationControl. The EventAnnotationControl
consists of a Line and a Border that contains a TextBlock.
- TextAnnotation: the TargetType for the
AnnotationElement is TextAnnotationControl and for
the MovingElement is
TextAnnotationHighlightElement. The
TextAnnotationControl consists of a TextBox and the
TextAnnotationHighlightElement represents the rectangle outlining
the TextBox. In order to change it's style, you need to set the
property TextRectangleStyle where the TargetType
should be Path.
- CalloutTextAnnotation: the TargetType for the
AnnotationElement is CalloutTextAnnotationControl
and for the MovingElement is
CalloutTextAnnotationHighlightElement. The
CalloutTextAnnotationControl is a TextAnnotationControl with a Line
and a Point. The Line connects the TextBox with the Point. In order
to style the Line, you need to set the LineStyle
of the CalloutTextAnnotationControl where the TargetType is Line
and in order to style the Point, you need to set the
PointStyle where the TargetType is Shape (by
default it's an ellipse but you can change that by providing your
own template). The CalloutTextAnnotationHighlightElement is a
TextAnnotationHighlightElement with a Line that can be styled by
setting the LineStyle property.
Custom Element Styles
Creating a custom style for one of the element styles is the
easiest and fastest way to change the styling of a specific state
of an annotation. For example, let's create a custom style for the
normal state of a RectangleAnnotation from code:
Setting styles from code
Style normal = new Style(typeof(Shape));
normal.Setters.Add(new Setter(Shape.FillProperty, new SolidColorBrush(Colors.LightGray)));
normal.Setters.Add(new Setter(Shape.StrokeProperty, new SolidColorBrush(Colors.DarkGray)));
normal.Setters.Add(new Setter(Shape.StrokeThicknessProperty, 1));
And assign it to a RectangleAnnotation:
RectangleAnnotation rect = new RectangleAnnotation(point1, point2);
rect.IsInteractionEnabled = true;
rect.AnnotationElementStyle = normal;
The annotation now uses the default styles for the selected and
highlight/moving states, and the custom style for the normal state.
Let's create a custom style for the other states as well and assign
them to the corresponding styles:
Style selected = new Style(typeof(Shape));
selected.Setters.Add(new Setter(Shape.StrokeThicknessProperty, 3));
selected.Setters.Add(new Setter(Shape.FillProperty, new SolidColorBrush(Colors.Blue)));
Style moving = new Style(typeof(Shape));
moving.Setters.Add(new Setter(Shape.StrokeProperty, new SolidColorBrush(Colors.Yellow)));
moving.Setters.Add(new Setter(Shape.StrokeThicknessProperty, 12));
moving.Setters.Add(new Setter(Shape.FillProperty, new SolidColorBrush(Colors.Transparent)));
Style movingCollapsed = new Style(typeof(Shape));
movingCollapsed.Setters.Add(new Setter(Shape.VisibilityProperty, Visibility.Collapsed));
rect.AnnotationElementSelectedStyle = selected;
rect.MovingElementStyle = moving;
rect.MovingElementCollapsedStyle = movingCollapsed;
Setting styles from XAML
Alternatively, you can set the same styles from XAML. In the
following example we will be styling a LineAnnotation from XAML.
First, we need to define the custom styles in our Resources:
<Style TargetType="Line" x:Key="CustomLineAnnotationElementStyle">
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="Stroke" Value="Magenta" />
</Style>
<Style TargetType="Line" x:Key="CustomLineAnnotationElementSelectedStyle">
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="Stroke" Value="Red" />
</Style>
<Style TargetType="Line" x:Key="CustomLineAnnotationMovingElementStyle">
<Setter Property="StrokeThickness" Value="12"/>
<Setter Property="Stroke" Value="Orange" />
<Setter Property="Opacity" Value="0.3" />
<Setter Property="StrokeStartLineCap" Value="Round"/>
<Setter Property="StrokeEndLineCap" Value="Round"/>
</Style>
<Style TargetType="Line" x:Key="CustomLineAnnotationMovingElementCollapsedStyle">
<Setter Property="Stroke" Value="Transparent" />
</Style>
Then, we need to set them from code to the various element
styles of a LineAnnotation:
LineAnnotation line = new LineAnnotation(point1, point2);
line.IsInteractionEnabled = true;
line.AnnotationElementStyle = Resources["CustomLineAnnotationElementStyle"] as Style;
line.AnnotationElementSelectedStyle = Resources["CustomLineAnnotationElementSelectedStyle"] as Style;
line.MovingElementStyle = Resources["CustomLineAnnotationMovingElementStyle"] as Style;
line.MovingElementCollapsedStyle = Resources["CustomLineAnnotationMovingElementCollapsedStyle"] as Style;
Custom Annotation Style
Setting each element style separately is useful when we want to
use the default annotation styles but change only the normal state
style, for example. If we want to override all the default element
styles, then we can create an annotation style and assign it to
it's Style property. So, for the RectangleAnnotation example
described above, we would not need to set all the individual styles
separately but wrap them all in one style:
//We don't need to it separately
//rect.AnnotationElementStyle = normal;
//rect.AnnotationElementSelectedStyle = selected;
//rect.MovingElementStyle = moving;
//rect.MovingElementCollapsedStyle = movingCollapsed;
Style s = new Style(typeof(RectangleAnnotation));
s.Setters.Add(new Setter(RectangleAnnotation.AnnotationElementStyleProperty, normal));
s.Setters.Add(new Setter(RectangleAnnotation.AnnotationElementSelectedStyleProperty, selected));
s.Setters.Add(new Setter(RectangleAnnotation.MovingElementStyleProperty, moving));
s.Setters.Add(new Setter(RectangleAnnotation.MovingElementCollapsedStyleProperty, movingCollapsed));
rect.Style = s;
And for the LineAnnotation example, we would need to add to the
Resources one more style:
<Style TargetType="charts:LineAnnotation" x:Key="CustomLineAnnotationStyle">
<Setter Property="AnnotationElementStyle" Value="{StaticResource CustomLineAnnotationElementStyle}" />
<Setter Property="AnnotationElementSelectedStyle" Value="{StaticResource CustomLineAnnotationElementSelectedStyle}" />
<Setter Property="MovingElementStyle" Value="{StaticResource CustomLineAnnotationMovingElementStyle}" />
<Setter Property="MovingElementCollapsedStyle" Value="{StaticResource CustomLineAnnotationMovingElementCollapsedStyle}" />
</Style>
And then set only one style from code:
line.Style = Resources["CustomLineAnnotationStyle"] as Style;
IMPORTANT: Setting a custom style to the
annotation will override all the element styles so you need to
define them all or you run the risk of your annotation not showing
anything in the states that have not been defined. Also, you will
notice that in both examples, the MovingElementCollapsedStyle is
either collapsed or invisible.
Implicit Annotation Style
Setting the styles from code behind makes the code look quite
messy, and I guess that it is most commonly used when we just want
to provide one custom element style. Defining the styles in XAML
and applying them to the annotation's Style property is a cleaner
way of providing our own styles but we still have to apply them to
each annotation separately. But what happens if we want to
apply a custom style to all the annotations of the same
type?
The answer to that is to use implicit styles. An implicit style
is a style defined in XAML as a Resource, but it does not have a
Resource key and so it is applied to all the elements of the
specified TargetType. So, in the LineAnnotation example, if we
don't provide a Key all the LineAnnotations will have the custom
style:
<Style TargetType="charts:LineAnnotation">
<Setter Property="AnnotationElementStyle" Value="{StaticResource CustomLineAnnotationElementStyle}" />
<Setter Property="AnnotationElementSelectedStyle" Value="{StaticResource CustomLineAnnotationElementSelectedStyle}" />
<Setter Property="MovingElementStyle" Value="{StaticResource CustomLineAnnotationMovingElementStyle}" />
<Setter Property="MovingElementCollapsedStyle" Value="{StaticResource CustomLineAnnotationMovingElementCollapsedStyle}" />
</Style>
From version 2.1 of the premium edition of Visiblox charts, we
include the default xaml files which contain the styles and
templates applied to all the elements of Visiblox charts. The
generic.DefaultTheme.xaml file contains all the annotation styles
applied by default (implicit styles).
Example
In the following example, you can see the above code in action.
Specifically, you can create RectangleAnnotations with the default
style and custom style applied, as well as LineAnnotations where
the implicit style is applied. The source code of the example can
be downloaded here and you will
need to add a reference to the premium Visiblox charts
library in order to compile it.
Conclusion
In this blog post we explored the different ways of styling
annotations, either from code or from XAML. Specifically, we looked
at the annotation elements (the elements that make up each
annotation), the styles provided for each of them and the impact
each of these styles has in the different states that an annotation
can be in.