2012-12-16 77 views
2

我目前在WPF中构建波形控制。 我打算建立一个缩放功能。这意味着用户应该有能力看到整个音频文件的每一个样本。众所周知...和audiofile可以有非常非常非常多的样本。所以我不得不画出极其多的线条,这将是开销。WPF线路虚拟化

所以我想到只有当他们被要求时才画线。问题是,我不知道什么是最好的,最干净的方式来做到这一点。你有什么想法,我可以开始建立这样一个功能。我不想让代码看起来像一个油炸的大脑。如果有人开始解决这个问题,我会非常感激。

回答

0

一种方法可以获得轨道的可见范围,然后绘制属于该区域的线。 This控制可能对您有所帮助。就个人而言,即使它不使用WPF的缩放功能,我也会将样本的坐标保持为只读集合,然后在需要渲染时将它们的组件乘以缩放因子。您将有ScrollViewerScrollableWidth(假设您的样本水平跨度)等于最后一个样本的乘以x坐标。获得上述效果的一种方法是始终绘制最后一个样本,而不将其连接到最后一个可见样本。最后,您将在您选择的容器中绘制可见线条,并将其用于ScrollViewer的Content属性。

使用CanvasScrollViewer添加一个小例子,您可以使用它在滚动/缩放时更新内容。

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;