【问题标题】:Scrollviewer containing Buttons for touchscreen useScrollviewer 包含用于触摸屏的按钮
【发布时间】:2012-09-06 16:37:12
【问题描述】:

我的目标是构建一个 ScrollViewer 类型的控件,其中包含一组按钮。 使用此滚动查看器控件的应用程序将安装在触摸屏终端上。 终端很可能会运行 Windows XP。

当按钮数量超出可视区域时,我希望用户能够使用手指水平滚动按钮。请注意,我不想显示任何滚动条。

我了解到“PanningMode”属性不能用于 windows xp,而只能用于触摸屏终端支持“Windows Touch”的 windows 7。

使用 WPF,我构建了一个屏幕,其中包含一个 scrollViewer 控件,该控件又具有一组按钮。我确实设法通过覆盖 windows previewMouseDown、previewMouseMove 事件来创建平移效果,但这会产生一个问题,即操作系统不知道用户是否按下滚动查看器以选择按钮或触摸滚动查看器以进行滚动。基本上,覆盖方法将始终获胜,并且按下左键将是真实的。

所以我需要一种能够滚动但仍保持在滚动查看器中单击(触摸)按钮的能力。

我将在下面附上我的示例代码。

如果有可能的方法来做到这一点,我会很高兴听到它:) 或者!!即使有这样的控件可供购买,我也会对此感兴趣。

非常感谢!

XAML:

 <Grid x:Name="LayoutSelector" Grid.Column="0" Grid.Row="1"  DataContext="{Binding Main, Source={StaticResource MainVM}}" Height="100" >
                        <ScrollViewer x:Name="ScrollViewer" Width="Auto" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" PanningMode="HorizontalOnly" >
                            <!--<ItemsControl ItemsSource="{Binding SelectedLayout}">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <WrapPanel HorizontalAlignment="Left" Height="100" />
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>-->
                            <StackPanel CanHorizontallyScroll="True" Orientation="Horizontal">
                                <Button x:Name="Test1" Content="Button1" Width="150"/>
                                <Button x:Name="Test2" Content="Button1" Width="150"/>
                                <Button x:Name="Test3" Content="Button1" Width="150"/>
                                <Button x:Name="Test4" Content="Button1" Width="150"/>
                                <Button x:Name="Test5" Content="Button1" Width="150"/>
                                <Button x:Name="Test6" Content="Button1" Width="150"/>
                                <Button x:Name="Test7" Content="Button1" Width="150"/>
                                <Button x:Name="Test8" Content="Button1" Width="150"/>
                                <Button x:Name="Test9" Content="Button1" Width="150"/>
                                <Button x:Name="Test10" Content="Button1" Width="150"/>
                                <Button x:Name="Test11" Content="Button1" Width="150"/>
                                <Button x:Name="Test12" Content="Button1" Width="150"/>
                            </StackPanel>


                        </ScrollViewer>
                    </Grid>

c#:

using System;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media.Effects;
using ViewModels;

namespace Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private Point scrollStartPoint;
    private Point scrollStartOffset;

    public MainWindow()
    {
        InitializeComponent();
        Closing += (s, e) => ViewModelCreator.Cleanup();
    }

    protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
    {
        if (ScrollViewer.IsMouseOver)
        {
            // Save starting point, used later when determining 
            //how much to scroll.
            scrollStartPoint = e.GetPosition(this);
            scrollStartOffset.X = ScrollViewer.HorizontalOffset;
            scrollStartOffset.Y = ScrollViewer.VerticalOffset;

            // Update the cursor if can scroll or not.
            this.Cursor = (ScrollViewer.ExtentWidth >
               ScrollViewer.ViewportWidth) ||
                (ScrollViewer.ExtentHeight >
                ScrollViewer.ViewportHeight) ?
               Cursors.ScrollAll : Cursors.Arrow;

            this.CaptureMouse();
        }

        base.OnPreviewMouseDown(e);
    }

    protected override void OnPreviewMouseMove(MouseEventArgs e)
    {
            //if (this.IsMouseCaptured)
            //{
                // Get the new scroll position.
                Point point = e.GetPosition(this);

                // Determine the new amount to scroll.
                Point delta = new Point(
                    (point.X > this.scrollStartPoint.X) ?
                        -(point.X - this.scrollStartPoint.X) :
                        (this.scrollStartPoint.X - point.X),

                    (point.Y > this.scrollStartPoint.Y) ?
                        -(point.Y - this.scrollStartPoint.Y) :
                        (this.scrollStartPoint.Y - point.Y));

                // Scroll to the new position.
                ScrollViewer.ScrollToHorizontalOffset(
                    this.scrollStartOffset.X + delta.X);
                ScrollViewer.ScrollToVerticalOffset(
                    this.scrollStartOffset.Y + delta.Y);
            //}

        base.OnPreviewMouseMove(e);
    }

    protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
    {
        if (this.IsMouseCaptured)
        {
            this.Cursor = System.Windows.Input.Cursors.Arrow;
            this.ReleaseMouseCapture();
        }

        base.OnPreviewMouseUp(e);
    }
}

}

【问题讨论】:

    标签: c# .net wpf touchscreen


    【解决方案1】:

    好吧,经过更多小时的摆弄和反复试验,我发现我想要保持功能性的点击事件是不可能的,因为执行了 mouseCapture 事件并按住鼠标防止任何进一步正在发生的动作,除了“PreviewMouseUp”事件,它在我左键单击时释放鼠标。

    所以我所做的是在进入或悬停在滚动查看器上时捕获鼠标位置,然后覆盖窗口的“OnPreviewMouseMove”方法以获取新位置。重要的是在“MouseEnter”事件中(未覆盖)我没有捕获鼠标,因此仍然允许鼠标单击滚动查看器中包含的按钮!

    代码如下!

    C#

    using System;
    using System.Globalization;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Markup;
    using System.Windows.Media.Effects;
    using ViewModels;
    
    namespace Views
    {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Point scrollStartPoint;
        private Point scrollStartOffset;
    
        public MainWindow()
        {
            InitializeComponent();
            Closing += (s, e) => ViewModelCreator.Cleanup();
        }
    
        //protected void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
        //{
        //    if (ScrollViewer.IsMouseOver)
        //    {
        //        // Save starting point, used later when determining 
        //        //how much to scroll.
        //        scrollStartPoint = e.GetPosition(this);
        //        scrollStartOffset.X = ScrollViewer.HorizontalOffset;
        //        scrollStartOffset.Y = ScrollViewer.VerticalOffset;
    
        //        // Update the cursor if can scroll or not.
        //        this.Cursor = (ScrollViewer.ExtentWidth >
        //           ScrollViewer.ViewportWidth) ||
        //            (ScrollViewer.ExtentHeight >
        //            ScrollViewer.ViewportHeight) ?
        //           Cursors.ScrollAll : Cursors.Arrow;
    
        //        this.CaptureMouse();
        //    }
    
        //    base.OnPreviewMouseDown(e);
        //}
    
        protected override void OnPreviewMouseMove(MouseEventArgs e)
        {
            if (ScrollViewer.IsMouseOver)
            {
                // Get the new scroll position.
                Point point = e.GetPosition(this);
    
                // Determine the new amount to scroll.
                Point delta = new Point(
                    (point.X > this.scrollStartPoint.X) ?
                        -(point.X - this.scrollStartPoint.X) :
                        (this.scrollStartPoint.X - point.X),
    
                    (point.Y > this.scrollStartPoint.Y) ?
                        -(point.Y - this.scrollStartPoint.Y) :
                        (this.scrollStartPoint.Y - point.Y));
    
                // Scroll to the new position.
                ScrollViewer.ScrollToHorizontalOffset(
                    this.scrollStartOffset.X + delta.X);
                ScrollViewer.ScrollToVerticalOffset(
                    this.scrollStartOffset.Y + delta.Y);
            }
    
            base.OnPreviewMouseMove(e);
        }
    
        private void ScrollViewer_MouseEnter(object sender, MouseEventArgs e)
        {
            if (ScrollViewer.IsMouseOver)
            {
                // Save starting point, used later when determining 
                //how much to scroll.
                scrollStartPoint = e.GetPosition(this);
                scrollStartOffset.X = ScrollViewer.HorizontalOffset;
                scrollStartOffset.Y = ScrollViewer.VerticalOffset;
    
                // Update the cursor if can scroll or not.
                this.Cursor = (ScrollViewer.ExtentWidth >
                   ScrollViewer.ViewportWidth) ||
                    (ScrollViewer.ExtentHeight >
                    ScrollViewer.ViewportHeight) ?
                   Cursors.Arrow : Cursors.Arrow;
            }
        }
    }
    }
    

    XAML:

                 <Grid x:Name="LayoutSelector" Grid.Column="0" Grid.Row="1"  DataContext="{Binding Main, Source={StaticResource MainVM}}" Height="100" >
                            <ScrollViewer x:Name="ScrollViewer" Width="Auto" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" PanningMode="HorizontalOnly"
                                          MouseEnter="ScrollViewer_MouseEnter"  >
                                <ItemsControl ItemsSource="{Binding SelectedLayout}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <WrapPanel HorizontalAlignment="Left" Height="100" />
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
    
                            </ScrollViewer>
                        </Grid>
    

    【讨论】:

      【解决方案2】:

      只是在一些更摆弄之后的更新。我更喜欢这段代码,因为我之前的回答意味着如果你想再次滚动,你必须将手指拖过滚动查看器,但要离开控件本身……没什么大不了的,但有些人可能会觉得这有点烦人。

      下面是当手指触摸控件时显示“ScrollAll”光标的替代方法,然后通过抬起并触摸其他地方,您可以从新位置恢复滚动,而无需将手指从控件上拖出。

      感谢 Sacha Barber,他的文章对帮助我完成这项工作非常有帮助:http://www.codeproject.com/Articles/48871/Friction-Scrolling-Now-An-WPF-Attached-Behaviour-T

      using System;
      using System.Globalization;
      using System.Threading;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Input;
      using System.Windows.Markup;
      using System.Windows.Media.Effects;
      using ViewModels;
      
      namespace Views
      {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
          private Point scrollStartPoint;
          private Point scrollStartOffset;
      
          public MainWindow()
          {
              InitializeComponent();
              Closing += (s, e) => ViewModelCreator.Cleanup();
          }
      
          protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
          {
              if (ScrollViewer.IsMouseOver)
              {
                  // Save starting point, used later when determining 
                  //how much to scroll.
                  scrollStartPoint = e.GetPosition(this);
                  scrollStartOffset.X = ScrollViewer.HorizontalOffset;
                  scrollStartOffset.Y = ScrollViewer.VerticalOffset;
      
                  // Update the cursor if can scroll or not.
                  this.Cursor = (ScrollViewer.ExtentWidth >
                     ScrollViewer.ViewportWidth) ||
                      (ScrollViewer.ExtentHeight >
                      ScrollViewer.ViewportHeight) ?
                     Cursors.ScrollAll : Cursors.Arrow;
      
                  //this.CaptureMouse();
              }
      
              base.OnPreviewMouseDown(e);
          }
      
          protected override void OnPreviewMouseMove(MouseEventArgs e)
          {
              if (this.Cursor == System.Windows.Input.Cursors.ScrollAll)
                  if (ScrollViewer.IsMouseOver)
                  {
                      // Get the new scroll position.
                      Point point = e.GetPosition(this);
      
                      // Determine the new amount to scroll.
                      Point delta = new Point(
                          (point.X > this.scrollStartPoint.X) ?
                              -(point.X - this.scrollStartPoint.X) :
                              (this.scrollStartPoint.X - point.X),
      
                          (point.Y > this.scrollStartPoint.Y) ?
                              -(point.Y - this.scrollStartPoint.Y) :
                              (this.scrollStartPoint.Y - point.Y));
      
                      // Scroll to the new position.
                      ScrollViewer.ScrollToHorizontalOffset(
                          this.scrollStartOffset.X + delta.X);
                      ScrollViewer.ScrollToVerticalOffset(
                          this.scrollStartOffset.Y + delta.Y);
                  }
      
              base.OnPreviewMouseMove(e);
          }
      
          //private void ScrollViewer_MouseEnter(object sender, MouseEventArgs e)
          //{
          //    if (ScrollViewer.IsMouseOver)
          //    {
          //        // Save starting point, used later when determining 
          //        //how much to scroll.
          //        scrollStartPoint = e.GetPosition(this);
          //        scrollStartOffset.X = ScrollViewer.HorizontalOffset;
          //        scrollStartOffset.Y = ScrollViewer.VerticalOffset;
      
          //        // Update the cursor if can scroll or not.
          //        this.Cursor = (ScrollViewer.ExtentWidth >
          //           ScrollViewer.ViewportWidth) ||
          //            (ScrollViewer.ExtentHeight >
          //            ScrollViewer.ViewportHeight) ?
          //           Cursors.Arrow : Cursors.Arrow;
          //    }
          //}
      
          protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
          {
              this.Cursor = System.Windows.Input.Cursors.Arrow;
              this.ReleaseMouseCapture();
      
              base.OnPreviewMouseUp(e);
          }
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-30
        • 2022-12-11
        • 1970-01-01
        • 2015-12-27
        • 2014-09-02
        • 1970-01-01
        • 2023-02-20
        • 2016-08-13
        相关资源
        最近更新 更多