【问题标题】:WPF ScrollViewer: tap=click, tap-and-hold/drag=scroll. How to achieve this?WPF ScrollViewer:点击=单击,点击并按住/拖动=滚动。如何做到这一点?
【发布时间】:2016-08-28 18:49:15
【问题描述】:

我正在开发一个 WPF 触摸应用程序。我有一个包含按钮的滚动查看器。我想在触摸拖动按钮时滚动显示,并在点击时调用按钮的命令。下面是一些开始使用的代码:

<Window x:Class="wpf_Button_Scroll.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:wpf_Button_Scroll"
    Title="MainWindow" Height="350" Width="200">
<Window.DataContext>
    <my:MyViewModel />
</Window.DataContext>

<Grid>
    <ScrollViewer>
        <ListView ItemsSource="{Binding MyData}" HorizontalAlignment="Stretch">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding}" 
                            Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" 
                            CommandParameter="{Binding}"
                            Margin="5 2" Width="150" Height="50"
                            FontSize="30" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ScrollViewer>
</Grid>
</Window>

还有视图模型:

namespace wpf_Button_Scroll
{
class MyViewModel
{
    public MyViewModel()
    {
        MyCommand = new ICommandImplementation();
    }

    public string[] MyData
    {
        get
        {
            return new string[]{
                "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
                "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
            };
        }
    }

    public ICommand MyCommand { get; private set; }

    private class ICommandImplementation : ICommand
    {
        public bool CanExecute(object parameter) { return true; }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter) { System.Windows.MessageBox.Show("Button clicked! " + (parameter ?? "").ToString()); }
    }
}
}

预期行为:

  1. 当用户点击按钮时,会出现一个消息框,其中包含“Button clicked!”文本。 ==> 好的

  2. 当用户按下按钮并移动手指(不松开)时,按钮会上下滚动 ==> NOK

如何在包含按钮的 ScrollViewer 中实现滚动?

我正在 Windows 7 上的 Visual Studio 2013 上进行开发,我的目标是具有相同代码库的 Windows 7 桌面和 Windows 8 平板电脑。框架 4.0。如果真的有必要,我可以升级到 4.5.2(我们有很多用户,所以升级并非易事)。

【问题讨论】:

  • 您的问题解决了吗? (我实际上希望这在默认情况下会起作用)
  • @H.B.是的,我的问题解决了。请参阅已接受的答案(我刚刚对其进行了编辑,因为它不是很清楚)。

标签: wpf xaml touch scrollviewer


【解决方案1】:

由于ListView 中有Button(s),因此我们必须让command 在预期时执行。这就是棘手的部分。我是通过以下方式做到的:

XAML:

<Window.DataContext>
    <local:MyViewModel />
</Window.DataContext>

<Grid>
    <ScrollViewer>
        <ListView ItemsSource="{Binding MyData}" HorizontalAlignment="Stretch" Name="listview" ScrollViewer.PanningMode="VerticalOnly">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding}"
                        Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" 
                        CommandParameter="{Binding}"
                        Margin="5 2" Width="150" Height="50"
                        FontSize="30" />
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.Resources>
                <Style TargetType="Button">
                    <EventSetter Event="PreviewMouseMove" Handler="PreviewMouseMove" />                        
                    <EventSetter Event="Drop" Handler="Drop" />                       
                    <Setter Property="AllowDrop" Value="True" />                        
                </Style>
            </ListView.Resources>
        </ListView>
    </ScrollViewer>
</Grid>

ViewModel:

class MyViewModel
{
    public MyViewModel()
    {
        MyCommand = new ICommandImplementation();
    }

    public ObservableCollection<string> MyData
    {
        get
        {
            return new ObservableCollection<string>(new string[]{
            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
            "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
            });
        }
    }

    public ICommand MyCommand { get; private set; }

    private class ICommandImplementation : ICommand
    {
        public bool CanExecute(object parameter) { return true; }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter) { System.Windows.MessageBox.Show("Button clicked! " + (parameter ?? "").ToString()); }
    }
}

事件:

 private void Drop(object sender, DragEventArgs e)
    {
        var source = e.Data.GetData("Source") as string;
        if (source != null)
        {
            int newIndex = listview.Items.IndexOf((sender as Button).Content);
            var list = listview.ItemsSource as ObservableCollection<string>;
            list.RemoveAt(list.IndexOf(source));
            list.Insert(newIndex, source);
        }
    }

    private void PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            Task.Factory.StartNew(new Action(() =>
                {
                    Thread.Sleep(500);
                    App.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            if (e.LeftButton == MouseButtonState.Pressed)
                            {                                    
                                var data = new DataObject();
                                data.SetData("Source", (sender as Button).Content);
                                DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move);
                                e.Handled = true;
                            }
                        }), null);
                }), CancellationToken.None);
        }           
    }

In this link 我写过Drag &amp; Drop 在事件及其数据共享方面的工作原理。

而且我还在研究滚动部分。

【讨论】:

  • 这是我没有问的问题的一半答案。 stackoverflow.com/questions/37008970/…
  • @DonkeyMaster ...我认为不是平板电脑而是鼠标拖动该链接会有所帮助...我知道这不是主题,但是例如我真的忘记了这些之后的问题很多天,只记得滚动问题部分...感谢您指出:)
【解决方案2】:

嗯,这太简单了,我为自己没有早点找到它而感到尴尬。我必须在 ScrollViewer 上设置 PanningMode 属性。

像这样:

<ScrollViewer PanningMode="VerticalOnly">

最终代码:

<Window x:Class="wpf_Button_Scroll.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:wpf_Button_Scroll"
    Title="MainWindow" Height="350" Width="200">
<Window.DataContext>
    <my:MyViewModel />
</Window.DataContext>

<Grid>
    <ScrollViewer PanningMode="VerticalOnly">
        <ListView ItemsSource="{Binding MyData}" HorizontalAlignment="Stretch">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding}" 
                            Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" 
                            CommandParameter="{Binding}"
                            Margin="5 2" Width="150" Height="50"
                            FontSize="30" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ScrollViewer>
</Grid>
</Window>

视图模型没有改变

【讨论】:

  • 你把这个属性具体放在哪里了?
  • @KyloRen 我澄清了我的答案
  • 好的..但我仍然卡在 WPF win 应用程序中的滚动部分... PanningMode="VerticalOnly" 似乎无法拖动..
  • 这个解决方案对我有用。如果对您有帮助,我可以添加整个代码。但如果我的解决方案对你不起作用,那么我们就有不同的问题了。
  • 请张贴 xaml 代码 .. 这会很有帮助...提前谢谢
猜你喜欢
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多