【问题标题】:Scrollable Canvas with movable items inside ScrollViewerScrollViewer 内带有可移动项目的可滚动画布
【发布时间】:2013-08-29 02:13:45
【问题描述】:

我有一个包含 Canvas 的 ScrollViewer。此画布上有一些可移动的 UIElement。这是我的 XAML 代码:

<ScrollViewer x:Name="Scroller" HorizontalScrollBarVisibility="Auto" Background="White">
       <Canvas x:Name="MapCanvas" Width="4000" Height="4000">    
                    <Button x:Name="TestBtn" 
                            Content="My button"
                            Canvas.Left="250"
                            ManipulationStarted="MapItem_ManipulationStarted"   
                            ManipulationDelta="MapItem_ManipulationDelta" 
                            ManipulationCompleted="MapItem_ManipulationCompleted"   
                            />                                  
      </Canvas>
</ScrollViewer>

这是事件处理程序的代码:

private void MapItem_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
        {
            FrameworkElement btn = sender as FrameworkElement;
            if (null == btn) return;            

            double left = Canvas.GetLeft(btn) + e.DeltaManipulation.Translation.X;
            double top = Canvas.GetTop(btn) + e.DeltaManipulation.Translation.Y;

            if (left < 0)
                left = 0;
            else if (left >  MapCanvas.ActualWidth - btn.ActualWidth)
                left = MapCanvas.ActualWidth - btn.ActualWidth;

            if (top < 0)
                top = 0;
            else if(top > MapCanvas.ActualHeight - btn.ActualHeight)
                top = MapCanvas.ActualHeight - btn.ActualHeight;

            Canvas.SetLeft(btn, left);
            Canvas.SetTop(btn, top);

            e.Handled = true;
        }

        private void MapItem_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
        {
            Scroller.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
            Scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;            

            e.Handled = true;
        }

        private void MapItem_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
        {
            Scroller.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
            Scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;

            e.Handled = true;
        }

一切都很完美。但是,当 ScrollViewer 滚动到某个 Horizo​​ntalOffset 或 VerticalOffset 并且我单击或点击可见区域中的任何 UIElement 时,ScrollViewer 似乎会自动滚动到 HorisontalOffset == 0 和 VerticalOffset == 0。然后,在释放 UIElement 后,它会跳回来。 如何避免这种行为并让 ScrollViewer 留在它的位置,而我会将 UIElement 拖到其中的 Canvas 中?

【问题讨论】:

    标签: c# .net wpf canvas windows-phone-8


    【解决方案1】:

    我发现我需要在页面构造函数中设置 ScrollViewer.ManipulationMode = ManipulationMode.Control 并且不设置 HorisontalScrollBarVisibility 和 VerticalScrollVarVisibility(它将偏移重置为 0,0 坐标) 现在可以了。

    谢谢!

    【讨论】:

      【解决方案2】:

      我尚未对此进行测试,但您可以尝试用禁用/重新启用 ScrollViewer 控件本身的调用替换(或添加)禁用/重新启用滚动条可见性的调用:

      private void MapItem_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
      {
          Scroller.IsEnabled = false;
      }
      
      private void MapItem_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
      {
          Scroller.IsEnabled = true;
      }
      

      如果它确实有效,它可能会在它被禁用时影响Style,因此当它等于False 时,您可能必须在IsEnabled 属性上使用Trigger 重新设置它的样式。

      【讨论】:

      • 问题是当 ScrollViewer 被禁用时,它里面的所有元素也会被禁用。所以我也不能移动它们:(
      • 我意识到这可能不是正确的路径,但是如果您扩展 Canvas 控件,您可以添加一个回调处理程序,以便在 IsEnabledProperty 更改时调用。然后在这个处理程序中,当Canvas 被禁用时,您可以将所有子项的IsEnabled 属性设置为true。看看this post,它有一个类似的例子,但是用TabItem 控件代替。
      猜你喜欢
      • 2014-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      • 1970-01-01
      相关资源
      最近更新 更多