none
DataGridView上をタッチした状態で拡大縮小、移動を行う。 RRS feed

  • 質問

  • Windowsタブレット用のアプリケーションを作成しています。

    画面の拡大縮小、移動を行いたいのですが、DataGridView上でうまく動作しません。

    良い方法はありますか?

    2019年4月15日 6:02

回答

  • DataGridの中にあるScrollViewerがManipulationイベントを先にハンドルしてしまうので、DataGridよりも外側ではイベントが取れないのです。

    Class MainWindow
    
        Sub New()
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            AddHandler Me.dgvResults.Loaded,
                Sub(s, e)
                    Dim sv As ScrollViewer = CType(Me.dgvResults.Template.FindName("DG_ScrollViewer", Me.dgvResults), ScrollViewer)
                    sv.IsManipulationEnabled = False
                End Sub
        End Sub
    
    
    ScrollViewerでManipulationを無効にすれば動作しますが、代わりにDataGrid内の要素をタッチでスクロールできなくなります。
    状況によって切り替えるなどの処理が必要になるでしょう。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク WPFNN 2019年4月16日 8:09
    2019年4月15日 14:17

すべての返信

  • 一般にDataGridViewというとSystem.Windows.Forms.DataGridViewのことを指すと思いますが、Windows Formsで制作されているのでしょうか。それとも、WPFのウィンドウにWindowsFormsHost経由でDataGridViewを載せているのでしょうか。あるいは、System.Windows.Forms.DataGridViewではないサードパーティー製のDataGridViewなのでしょうか。

    「画面の拡大縮小」の「画面」というのは何を意味するのでしょうか。

    「拡大縮小」というのはどういうものを指すのでしょうか。拡大縮小で真っ先に思いつくのは「表示されてるセルとか文字とかが大きく/小さくなる」ですが、「画面の」という修飾が付いているとしっくりきません。

    「移動」というのは、ウィンドウ(フォーム)の移動なのか、DataGridViewというコントロールだけの移動なのか、どちらでもない別の物の移動なのか、どれでしょうか。

    「DataGridView上でうまく動作しません」というのは、DataGridView上以外ではうまく動作している処理が存在しているということでしょうか。それはどんなコントロール上において、どんな記述やデザイナでの設定をした結果(あるいは特に記述しなくてもなのか)、どういう結果になって「うまく動作した」ということになりましたか。

    「タッチした状態で」というのはどういうものでしょうか。「タッチ操作によって」と読み替えていいのでしょうか。

    2019年4月15日 7:28
  • ご回答誠にありがとうございます。

    >一般にDataGridViewというとSystem.Windows.Forms.DataGridViewのことを指すと思いますが、Windows Formsで制作されているのでしょうか。それとも、WPFのウィンドウにWindowsFormsHost経由でDataGridViewを載せているのでしょうか。あるいは、System.Windows.Forms.DataGridViewではないサードパーティー製のDataGridViewなのでしょうか。

    申し訳ございません、「DataGridView」ではなく「DataGrid」の間違いでした。制作はWPFのウインドウのCanvas、Gridの上にDataGridを載せているかたちになります。

    >「画面の拡大縮小」の「画面」というのは何を意味するのでしょうか。

    WPFのGridを意味します。

    >「拡大縮小」というのはどういうものを指すのでしょうか。拡大縮小で真っ先に思いつくのは「表示されてるセルとか文字とかが大きく/小さくなる」ですが、「画面の」という修飾が付いているとしっくりきません。

    初期表示の縦横比を保ちながら文字等が拡大縮小されることを指します。

    >「移動」というのは、ウィンドウ(フォーム)の移動なのか、DataGridViewというコントロールだけの移動なのか、どちらでもない別の物の移動なのか、どれでしょうか。

    DataFridを含むGridの移動になります。

    >「DataGridView上でうまく動作しません」というのは、DataGridView上以外ではうまく動作している処理が存在しているということでしょうか。

    はい、DataGridの範囲外で2本指でピンチイン・ピンチアウトをするとGridは正しく拡大縮小されます。ですが、片方の指がDataGrid上に触れているとおそらく2本で触れていると認識されず、DataGrid外で触れている指のみ認識されるため、Gridが移動してしまいます。

    >それはどんなコントロール上において、どんな記述やデザイナでの設定をした結果(あるいは特に記述しなくてもなのか)、どういう結果になって「うまく動作した」ということになりましたか。

    以下がコードになります。

    Private Sub Window_ManipulationDelta(sender As Object, e As ManipulationDeltaEventArgs)
            Dim Rect = TryCast(e.OriginalSource, Grid)
            If Rect IsNot Nothing Then
                Dim rectsMatrix = (CType(Rect.RenderTransform, MatrixTransform)).Matrix
    
                'オブジェクトの移動を行う。
                rectsMatrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y)
    
                'オブジェクトの拡大縮小を行う。
                rectsMatrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y, _
                                    e.ManipulationOrigin.X, e.ManipulationOrigin.Y)
    
                Rect.RenderTransform = New MatrixTransform(rectsMatrix)
                e.Handled = True
    
            End If
    
    End Sub
    
    Private Sub btnSearch_PreviewTouchDown(sender As Object, e As TouchEventArgs) Handles btnSearch.PreviewTouchDown
    
            Dim Items As New List(Of Item)
            For I As Integer = 0 To 50
                Items.Add(New Item With {.code = "項目1" + I.ToString(), .name = "項目2" + I.ToString()})
            Next
    
            dgvResults.ItemsSource = Items
    
     End Sub
    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:MyNamespace="clr-namespace:sample"
        xmlns:System="clr-namespace:System;assembly=mscorlib" x:Name="window"
        mc:Ignorable="d" x:Class="SAMPLE"
        Title="sample" Height="535" Width="484" Background="Cornsilk" MaxHeight="535" MaxWidth="484" MinHeight="535" MinWidth="484" ManipulationStarting="Window_ManipulationStarting" ManipulationDelta="Window_ManipulationDelta" ResizeMode="NoResize">
        <Window.Resources>
            <Style x:Key="HeaderCenterStyle" TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="HorizontalContentAlignment" Value="Center" />
            </Style>
        </Window.Resources>
        <Canvas x:Name="board" Height="500" Width="472" Background="Cornsilk" OpacityMask="Cornsilk" IsManipulationEnabled="True">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="matrixtransform">
                    <MatrixTransform.Matrix>
                        <Matrix OffsetX="0" OffsetY="0"/>
                     </MatrixTransform.Matrix>
                </MatrixTransform>
            </Canvas.RenderTransform>
            <Grid x:Name="grid" HorizontalAlignment="Center" VerticalAlignment="Center" IsManipulationEnabled="True" Background="Cornsilk" OpacityMask="Cornsilk">
                <Button x:Name="btnBack" Content="閉じる" HorizontalAlignment="Left" VerticalAlignment="Top" Width="90" Height="30" Margin="9,9,0,0" FontFamily="MS UI Gothic"/>
                <Label x:Name="lblTitle" Content="サンプル" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="124,30,0,0" FontFamily="MS UI Gothic" FontSize="19.5" FontWeight="Bold" Height="40" Width="240" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="0" Background="Cornsilk"/>
                <Button x:Name="btnSearch" Content="ボタン" HorizontalAlignment="Left" Width="40" Height="25" Grid.Column="1" Grid.Row="2" Margin="380,100,0,0" VerticalAlignment="Top" FontFamily="MS UI Gothic"/>
                <DataGrid x:Name="dgvResults" HorizontalAlignment="Left" Height="330" Width="460" AutoGenerateColumns="False" CanUserReorderColumns="False" IsReadOnly="True" Padding="0" VerticalAlignment="Top" FontFamily="MS UI Gothic" Margin="5,160,0,0" RowHeight="21" VerticalContentAlignment="Center" Canvas.Left="0" Canvas.Top="0">
                    <DataGrid.Resources>
                        <Style TargetType="DataGridCell">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                                        <Grid Background="{TemplateBinding Background}">
                                            <ContentPresenter VerticalAlignment="Center"/>
                                        </Grid>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </DataGrid.Resources>
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding code}" Header="項目1" Width="150" FontFamily="MS UI Gothic"/>
                        <DataGridTextColumn Binding="{Binding name}" Header="項目2" Width="*" FontFamily="MS UI Gothic" HeaderStyle="{StaticResource HeaderCenterStyle}"/>
                    </DataGrid.Columns>
                </DataGrid>
            </Grid>
        </Canvas>
    </Window>

    つたない返信で申し訳ありませんが、ご回答宜しくお願い致します。
    2019年4月15日 9:19
  • DataGridの中にあるScrollViewerがManipulationイベントを先にハンドルしてしまうので、DataGridよりも外側ではイベントが取れないのです。

    Class MainWindow
    
        Sub New()
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            AddHandler Me.dgvResults.Loaded,
                Sub(s, e)
                    Dim sv As ScrollViewer = CType(Me.dgvResults.Template.FindName("DG_ScrollViewer", Me.dgvResults), ScrollViewer)
                    sv.IsManipulationEnabled = False
                End Sub
        End Sub
    
    
    ScrollViewerでManipulationを無効にすれば動作しますが、代わりにDataGrid内の要素をタッチでスクロールできなくなります。
    状況によって切り替えるなどの処理が必要になるでしょう。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク WPFNN 2019年4月16日 8:09
    2019年4月15日 14:17
  • ご回答ありがとうございます。

    教えていただいたソースコードを参考に実装してみたところ、Gridの拡大・縮小、移動が行えました。

    スクロールバーの動作に制限がかかる件も含めて内部で相談し方針を決めていきたいと思います。

    2019年4月16日 6:35