首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >让Viewbox和ScrollViewer协同工作

让Viewbox和ScrollViewer协同工作
EN

Stack Overflow用户
提问于 2013-11-29 22:21:36
回答 2查看 2.7K关注 0票数 19

我有一个正在玩的地图,我使用ScrollViewer在地图上移动,我希望结合使用ViewBoxPinchManipulations来放大和缩小地图。到目前为止,我已经通过将ScrollViewerManipulation模式设置为control来做到这一点,但是这会让我在缩放时出现延迟。有没有办法让ViewBoxScrollViewer更好地协同工作,从而避免滞后?到目前为止,我得到的代码是:

ScrollViewer:

代码语言:javascript
复制
<ScrollViewer Grid.Column ="0"  Width="768" Height="380" HorizontalScrollBarVisibility="Hidden">
    <Viewbox Stretch="None">
        <View:Map/>
    </Viewbox>
</ScrollViewer>

PinchZoom:

代码语言:javascript
复制
<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>

我使用收缩缩放的代码如下:

代码语言:javascript
复制
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);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-04 21:02:04

我认为您应该改为查看viewportcontroller,并查看基本的镜头示例,他们在那里实现了这一点。viewportcontroller内部有一个滚动查看器和一个viewport。

基本情况如下:

  1. 当您拥有的图像是“未缩放”时,scrollviewer拥有完全的控制权,而ViewportControl什么也不做。
  2. 当您开始收缩时,通过禁用垂直滚动条并设置viewport.height = scrollviewer.height来锁定滚动查看器。这中和了scollviewer。你可以使用ScaleTransform.
  3. On
  4. 进行临时缩放,调整实际图像的大小,使其占据ViewportControl内部的实际空间。现在你的viewportControl可以让你用漂亮的bounce-back.
  5. When平移所有放大的图像,你再次缩小,重新启用滚动查看器。(将高度设置为屏幕高度并打开滚动条。)

仅供参考,我完全忘记了为什么里面有画布,但我觉得它很重要。如下所示:

虽然下面的示例没有完成您想要做的事情,但我的代码基于此示例中的MediaViewer并对其进行了修改:Basic Lens Sample

然而,应该注意的是,它是用于图片缩放的。

票数 1
EN

Stack Overflow用户

发布于 2014-02-27 16:49:38

当我试图在一个容器中处理大量数据时,我也遇到了这个问题。您不能简单地将整个地图加载到viewbox中,然后使用滚动查看器,然后期望一切都能正常工作。

要使应用程序在大数据集上表现良好,第一个解决方案是尝试UI虚拟化。接受虚拟化的控件只创建显示当前视图所需的元素,或者更准确地说,只创建在显示器上可见的元素。为了更好地理解这个概念,我将给你一个真实的例子。看看Facebook是如何呈现其新闻提要的。它加载X个html元素中的X个帖子,然后当用户向下滚动时,它卸载不可见的帖子并加载新的帖子。

1.虚拟化

它只是简单地重用元素。这就是UI虚拟化的概念。我不得不提到一个重要的特性:延迟滚动(用户可以滚动,但结果只在点击释放后显示,如果用户喜欢上下滚动条,这是一个性能改进)

回到你的问题上。如果地图是完全加载的,则滚动或放大是一个性能问题,因为不可见的部分也会缩放和滚动。想象一下,如果Google Maps不支持UI虚拟化,会发生什么。当用户试图放大时,所有的地球都会放大(以吨为单位)。

2.数据虚拟化

但是,您的地图应该完全加载到内存中的某个位置。如果它很大,这就是一个问题,然后就出现了数据虚拟化。它只加载需要显示的部分,而不是完全加载所有地图。如果您希望获得更好的响应能力,可以使用Google Maps使用的概念。在渲染时,加载到内存中的数据要比显示时显示的数据多一些,这样当您尝试滚动时,UI就不会冻结(直到数据被放入内存)。

你可以阅读更多:

  1. Implementing virtualized panel
  2. Item container generator
  3. Measure core
  4. Results

我用Virtualized Canvas解决了我的问题。使用虚拟化画布的应用程序示例:http://pavzav.blogspot.ro/2010/11/virtualized-canvas.html

您可能想看看Wpf Bing Maps Control

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20287846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档