我有一个正在玩的地图,我使用ScrollViewer
在地图上移动,我希望结合使用ViewBox
和PinchManipulations
来放大和缩小地图。到目前为止,我已经通过将ScrollViewer
的Manipulation
模式设置为control
来做到这一点,但是这会让我在缩放时出现延迟。有没有办法让ViewBox
和ScrollViewer
更好地协同工作,从而避免滞后?到目前为止,我得到的代码是:
ScrollViewer:
<ScrollViewer Grid.Column ="0" Width="768" Height="380" HorizontalScrollBarVisibility="Hidden">
<Viewbox Stretch="None">
<View:Map/>
</Viewbox>
</ScrollViewer>
PinchZoom:
<Grid x:Name="Map" Width="1271" Height="1381.5">
<Grid.RenderTransform>
<ScaleTransform ScaleX="{Binding Path=deltaZoom}" ScaleY="{Binding Path=deltaZoom}"/>
</Grid.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger EventName="ManipulationStarted">
<cmd:EventToCommand Command="{Binding Path=ZoomStartedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="ManipulationDelta">
<cmd:EventToCommand Command="{Binding Path=ZoomDeltaCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="ManipulationCompleted">
<cmd:EventToCommand Command="{Binding Path=ZoomCompletedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
我使用收缩缩放的代码如下:
public ICommand ZoomStartedCommand { get; set; }
public ICommand ZoomDeltaCommand { get; set; }
public ICommand ZoomCompletedCommand { get; set; }
private double _deltaZoom;
public double deltaZoom
{
get
{
return _deltaZoom;
}
set
{
_deltaZoom = value;
RaisePropertyChanged("deltaZoom");
}
}
public double distance;
public MainViewModel()
{
ZoomStartedCommand = new RelayCommand<ManipulationStartedEventArgs>(ZoomStart);
ZoomDeltaCommand = new RelayCommand<ManipulationDeltaEventArgs>(ZoomDelta);
ZoomCompletedCommand = new RelayCommand<ManipulationCompletedEventArgs>(ZoomCompleted);
}
public void ZoomStart(ManipulationStartedEventArgs e)
{
FrameworkElement Element = (FrameworkElement)e.OriginalSource;
var myScrollViewer = FindParentOfType<ScrollViewer>(Element) as ScrollViewer;
myScrollViewer.SetValue(ScrollViewer.ManipulationModeProperty, ManipulationMode.Control);
}
public void ZoomDelta(ManipulationDeltaEventArgs e)
{
if (e.PinchManipulation != null)
{
deltaZoom = deltaZoom * e.PinchManipulation.DeltaScale;
}
else
{
FrameworkElement Element = (FrameworkElement)e.OriginalSource;
var myScrollViewer = FindParentOfType<ScrollViewer>(Element) as ScrollViewer;
myScrollViewer.SetValue(ScrollViewer.ManipulationModeProperty, ManipulationMode.System);
}
}
public void ZoomCompleted(ManipulationCompletedEventArgs e)
{
FrameworkElement Element = (FrameworkElement)e.OriginalSource;
var myScrollViewer = FindParentOfType<ScrollViewer>(Element) as ScrollViewer;
myScrollViewer.SetValue(ScrollViewer.ManipulationModeProperty, ManipulationMode.System);
}
发布于 2014-03-04 21:02:04
我认为您应该改为查看viewportcontroller,并查看基本的镜头示例,他们在那里实现了这一点。viewportcontroller内部有一个滚动查看器和一个viewport。
基本情况如下:
仅供参考,我完全忘记了为什么里面有画布,但我觉得它很重要。如下所示:
虽然下面的示例没有完成您想要做的事情,但我的代码基于此示例中的MediaViewer并对其进行了修改:Basic Lens Sample
然而,应该注意的是,它是用于图片缩放的。
发布于 2014-02-27 16:49:38
当我试图在一个容器中处理大量数据时,我也遇到了这个问题。您不能简单地将整个地图加载到viewbox中,然后使用滚动查看器,然后期望一切都能正常工作。
要使应用程序在大数据集上表现良好,第一个解决方案是尝试UI虚拟化。接受虚拟化的控件只创建显示当前视图所需的元素,或者更准确地说,只创建在显示器上可见的元素。为了更好地理解这个概念,我将给你一个真实的例子。看看Facebook是如何呈现其新闻提要的。它加载X个html元素中的X个帖子,然后当用户向下滚动时,它卸载不可见的帖子并加载新的帖子。
1.虚拟化
它只是简单地重用元素。这就是UI虚拟化的概念。我不得不提到一个重要的特性:延迟滚动(用户可以滚动,但结果只在点击释放后显示,如果用户喜欢上下滚动条,这是一个性能改进)
回到你的问题上。如果地图是完全加载的,则滚动或放大是一个性能问题,因为不可见的部分也会缩放和滚动。想象一下,如果Google Maps不支持UI虚拟化,会发生什么。当用户试图放大时,所有的地球都会放大(以吨为单位)。
2.数据虚拟化
但是,您的地图应该完全加载到内存中的某个位置。如果它很大,这就是一个问题,然后就出现了数据虚拟化。它只加载需要显示的部分,而不是完全加载所有地图。如果您希望获得更好的响应能力,可以使用Google Maps使用的概念。在渲染时,加载到内存中的数据要比显示时显示的数据多一些,这样当您尝试滚动时,UI就不会冻结(直到数据被放入内存)。
你可以阅读更多:
我用Virtualized Canvas解决了我的问题。使用虚拟化画布的应用程序示例:http://pavzav.blogspot.ro/2010/11/virtualized-canvas.html
您可能想看看Wpf Bing Maps Control
https://stackoverflow.com/questions/20287846
复制相似问题