0

ボタンの配列を保持する ScrollViewer タイプのコントロールを構築することを目指しています。この scrollviewer コントロールを使用するアプリケーションは、タッチスクリーン端末にインストールされます。端末はおそらく Windows XP を実行しています。

表示可能な領域に収まらないボタンが多い場合、ユーザーが指を使用してボタンを水平方向にスクロールできるようにしたいと考えています。スクロールバーを表示したくないことに注意してください。

「PanningMode」プロパティは Windows XP では使用できず、タッチスクリーン端末が「Windows Touch」をサポートする Windows 7 のみで使用できることを知りました。

WPF を使用して、ボタンのコレクションを持つ scrollViewer コントロールを含む画面を作成しました。Windows の previewMouseDown、previewMouseMove イベントをオーバーライドすることでパンニング効果を作成することができましたが、これにより、ユーザーがスクロールビューアーを押してボタンを選択したのか、スクロールするためにスクロールビューアーに触れたのかをオペレーティング システムが認識できないという問題が発生します。基本的にオーバーライド メソッドは常に優先され、左ボタンを押すと true になります。

したがって、スクロールできるようにする方法が必要ですが、スクロールビューア内のボタンをクリック (タッチ) する機能を維持する必要があります。

以下にサンプルコードを添付します。

これを行う方法があれば、それを聞いて喜んでいます:)または!! そのようなコントロールが購入できる場合でも、私はそれにも興味があります。

どうもありがとう!

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

}

4

2 に答える 2

0

わかりましたので、さらに何時間もいじって試行錯誤した後、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>
于 2012-09-07T09:01:18.693 に答える
0

もう少しいじった後の更新です。私の以前の答えは、スクロールビューアー上で指をドラッグする必要があることを意味するため、このコードの方が気に入っていますが、もう一度スクロールしたい場合はコントロール自体から離れます...大したことではありませんが、少し面倒だと感じる人もいます。

以下は、指がコントロールに触れたときに 'ScrollAll' カーソルを表示する別の方法です。指を離して別の場所に触れると、コントロールから指をドラッグすることなく、新しい位置からスクロールを再開できます。

Sacha Barber の功績もあり、その記事は私がこれを完了するのに非常に役立ちました

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

}

于 2012-09-07T09:35:22.277 に答える