我的目标是构建一个ScrollViewer类型的控件,它包含一组按钮。 使用此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);
}
}
}
答案 0 :(得分:0)
好的,经过多个小时的摆弄和反复试验后,我发现因为mouseCapture事件被执行并且不让任何进一步的鼠标阻止,因此无法实现我想要保持功能的点击事件。发生的动作,除了我点击左键时释放鼠标的'PreviewMouseUp'事件。
所以我所做的就是在进入或悬停在scrollviewer上时捕获鼠标位置,然后覆盖窗口的'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>
答案 1 :(得分:0)
经过一些更多的摆弄后,只是一个更新。我更喜欢这段代码,因为我之前的回答意味着你要在滚动浏览器上拖动手指,但如果你想再次滚动则关闭控件本身......不是什么大不了的事,但是有些人可能觉得它有点讨厌。
下面是手指触摸控件时显示'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);
}
}
}