Skip to content

Components

g$ edited this page May 24, 2018 · 11 revisions

The rendering subsystem is broken down into many small interfaces which form a Pipeline executed by the Chart. See Rendering for more details.

Every ChartComponent subclass should implement (some of) the core "require" interfaces:

  • IRequireLayout: claim space for rendering.
  • IRequireLayoutComplete: be notified of final size and position.
  • One of the following:
    • IRequireRender: create Geometry for non-series components (e.g. decorations and axes).
    • IDataSourceRenderer: hooks into DataSource rendering pipeline (DSRP).
    • IProvideDataSourceRenderer: indirectly provide an instance of IDataSourceRenderer.
  • IRequireAfterAxesFinalized: be notified when axis-extent transfer for all components is completed.
    • Must not be implemented by IChartAxis components.
  • IRequireTransforms: adjust Path geometry Transforms based on current size.

and the Visual Tree related interface:

  • IRequireEnterLeave: obtain Layer, link to other ChartComponent as required, undo the effects of enter.

Visual Tree

The ChartComponents do not directly participate in the Visual Tree. The Chart owns the root of the VT, via a Canvas in its control template. Components add their individual drawable elements to a Layer; in particular Path with associated Geometry.

The Layer provides a convenient "container" a component can work with for its visual children. It also hides how the hosting Chart chooses to organize these elements in its own visual tree.

A good example is an Axis. It has several visual elements:

  • the axis "bar" (a Path)
  • the tick labels (some TextBlocks)

Because a ChartComponent gets access to the rendering areas available (its own plus the common area), it can place Layers wherever necessary, and adjust Transforms as required, usually a different Transform for each Path. Other elements like TextBlock require translation to XAML coordinates for placement, also using a Transform.

In order to create visual elements, a ChartComponent must implement IRequireEnterLeave and obtain a Layer.

Most components only need a single Layer to operate properly.

Axis Extents

In order to participate in the render pipeline's axis extent transfer phase, a component must implement the IProvideValueAxisExtents interface, when bound to the value axis:

  • A DataSeries is bound to both axes.
  • A HorizontalRule is bound to the value axis.

A component must do axis extent bookkeeping while creating Geometry.

Series Components

  • All series must
    • subclass the DataSeries (or its subclasses) to be considered a series,
  • Should implement
    • IDataSourceRenderer to observe the DataSource values and create Geometry,
    • IRequireAfterAxesComplete to make calculations based on axis extents,
    • IRequireTransforms to adjust transforms.
  • Should not implement
    • IRequireLayout because the data region is used instead.

Axis Components

  • All axes must
    • subclass AxisCommon,
    • implement IChartAxis to be considered an axis.
  • Should implement
    • IRequireLayout to claim space,
    • IRequireLayoutComplete to position and size Layer,
    • IRequireTransforms to adjust transforms.
  • A value axis should implement:
    • IRequireRender to generate Geometry.
  • A category axis should implement:
    • (One of) the DSRP interface(s) so it can track values and labels.
  • Must not implement
    • IRequireAfterAxesComplete because IRequireRender for an axis runs after axis extents are finalized.

Decoration Components

Any other visual presentation than DataSeries et al or IChartAxis is considered a generic decoration.

  • All decorations must
    • subclass ChartComponent.
  • Should implement
    • IRequireLayout to claim space,
    • IRequireLayoutComplete to position and size Layer,
    • IRequireRender to generate Geometry,
    • IRequireAfterAxesComplete to make calculations based on axis extents,
    • IRequireTransforms to adjust transforms.
Clone this wiki locally