2012-09-06 58 views
0

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

我想要用户能够使用他们的手指水平滚动浏览按钮,当有更多的按钮比适合可视区域。请注意,我不想显示任何滚动条。

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

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

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

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

如果有一种可能的方法来做到这一点,我会被要求听到它:)或!!即使有可供购买的这种控制,我也会对此感兴趣。

非常感谢!

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); 
    } 
} 

}

回答

0

好了那么多的时间摆弄和反复试验,它发生在我的点击事件,这是后什么我想保持funcionality是不可能的,因为mouseCapture事件被执行并且阻止鼠标阻止任何进一步的动作发生,除了'PreviewMouseU p'事件,当我离开鼠标时释放鼠标。

所以我所做的就是捕获鼠标在进入或悬停在scrollviewer上的位置,然后覆盖窗口的'OnPreviewMouseMove'方法以获取新的位置。重要的是'MouseEnter'事件(未覆盖)我没有捕获鼠标,鼠标仍然被允许点击scrollviewer中包含的按钮!

代码如下所示!

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> 
0

只是一个更新后一些更多的摆弄。我更喜欢这个代码,因为我以前的回答意味着你必须拖动你的手指越过滚动查看器,但如果你想再次滚动则关闭控制器本身......不是一个大问题,但有些人可能会觉得有点烦人。

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

信贷萨沙理发太,其文章都非常有帮助,帮助我完成这个: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); 
    } 
} 

}