A way to achieve that could be obtaining the visible range of the track, then draw lines belonging to that region. This control could be helpful to you. Personally, even if it wouldn't use WPF's zooming features, I'd keep the samples' coordinates in a readonly collection, then multiply their components by the zoom factor when a rendering is demanded. You would have a ScrollViewer
with ScrollableWidth
(assuming that your samples spans horizontally) equals to the last sample's multiplied x coordinate. One way to obtain the above effect would be always drawing the last sample, without connecting it to the last visible one. Finally, you would draw the visible lines in a container of your choice and use it for the ScrollViewer's Content
property.
Adding a small example using a Canvas
and a ScrollViewer
, you can use it to update the content upon scrolling/zooming.
var scrollViewer = _scrollViewer; //_scrollViewer is our container
var min = scrollViewer.ContentHorizontalOffset; //Calculating visible ranges
var max = min + scrollViewer.ViewportWidth;
int[] samples = { 10, 20, 30, 50, 80, 90, 100, 130 }; //Our original samples
const double zoomFactor = 10.0;
var canvas = new Canvas {HorizontalAlignment = HorizontalAlignment.Left};
foreach (var sampleX in samples)
{
var multipliedX = sampleX*zoomFactor;
if (multipliedX < min || multipliedX > max) continue;
var sampleCircle = new Ellipse {Width = 5, Height = 5, Stroke = Brushes.Black}; //Our Shape for the sample
canvas.Children.Add(sampleCircle);
Canvas.SetLeft(sampleCircle, multipliedX);
}
canvas.Width = samples.Last()*zoomFactor; //To extend the ScrollViewer's scrollable width
scrollViewer.Content = canvas;