windows8.1中的WPF操作

windows8.1中的WPF操作,wpf,rotation,translation,scaling,multi-touch,Wpf,Rotation,Translation,Scaling,Multi Touch,有人能提供一些链接到如何在Windows8.1中进行操作的示例吗 我在网上看到了很多关于如何在Windows7上实现这一点的例子,但在我的Windows8.1机器(带触摸屏)上它并不适用于我。我正在使用VS Studio社区v15。以下是我一直在尝试的示例: 使用鼠标或手指都不会使任何事情发生-没有移动,没有缩放,没有旋转,等等 另外,我是用VB做我的项目,不是用C 比如说, <Window x:Class = "WpfManipulation1.MainWindow" xmln

有人能提供一些链接到如何在Windows8.1中进行操作的示例吗

我在网上看到了很多关于如何在Windows7上实现这一点的例子,但在我的Windows8.1机器(带触摸屏)上它并不适用于我。我正在使用VS Studio社区v15。以下是我一直在尝试的示例:

使用鼠标或手指都不会使任何事情发生-没有移动,没有缩放,没有旋转,等等

另外,我是用VB做我的项目,不是用C

比如说,

<Window x:Class = "WpfManipulation1.MainWindow" 
   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:local = "clr-namespace:WpfManipulation1" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

    <Window.Resources>
        <MatrixTransform x:Key = "InitialMatrixTransform">
            <MatrixTransform.Matrix>
                <Matrix OffsetX = "200" OffsetY = "200"/>
            </MatrixTransform.Matrix>
        </MatrixTransform>
    </Window.Resources>

    <Canvas>
        <Rectangle Name = "manRect" Width = "321" Height = "241"  
         RenderTransform = "{StaticResource InitialMatrixTransform}" 
         IsManipulationEnabled = "true" Canvas.Left = "-70" Canvas.Top = "-170">
            <Rectangle.Fill>
                <ImageBrush ImageSource = "ManipImage.JPG"/>
            </Rectangle.Fill>
        </Rectangle>
        <Image Source="ManipImage.jpg" ManipulationMode="All" ManipulationDelta="UIElement_OnManipulationDelta" />
    </Canvas>

</Window>
“Dim transformGroup=CType(element.RenderTransform,transformGroup)”行出错:System.InvalidCastException:“无法将类型为”System.Windows.Media.MatrixTransform“的对象强制转换为类型为”System.Windows.Media.transformGroup“。”

下面是实施所提供建议的结果

XAML:


代码隐藏(VB):

”参考:http://www.wpf-tutorial.com/common-interface-controls/toolbar-control/
导入系统
导入系统.Windows
导入System.Windows.Input
导入System.Windows.Media
导入System.Windows.Shapes
命名空间WpfTutorialSamples.Common_接口_控件
公共类工具栏示例
继承窗口
Dim CausedByCode为布尔值
变暗缩放因子为双精度=0.1
双精度缩放最大值=4.95
变暗变焦为双精度=0.05
Dim NumberOfLevel为整数=6
Dim NumberOfCellsPerLevel为整数=2
尺寸LvlBuffer为双精度=0.02
双精度单元格缓冲区=0.05
Dim LvlContainerColor As Brush=笔刷。浅绿色
Dim CellContainerColor作为笔刷=笔刷。浅黄色
将LvlDividerColor变暗为画笔=画笔。红色
公共分新()
我的基地,新的
初始化组件()
端接头
Private Sub MainWindow_Initialized(发送方作为对象,e作为事件参数)处理我。Initialized
'HideWindows(False,New StackPanel(){StackPanel_NW,StackPanel_SE,StackPanel_SW})
HideWindows(True,New StackPanel(){})'all
端接头
Private Sub Main Window_Loaded(发件人作为对象,e作为事件参数)处理我。Loaded
'添加分隔符
对于a=1到(NumberOfLevel-1)
顶部调暗为双色=a*(manRect.Height/NumberOfLevels)
将LVLDIVIER变暗为新画布
LvlDivider.Background=LvlDividerColor
LvlDivider.Width=manRect.Width
LvlDivider.高度=0.25
manRect.Children.Add(LvlDivider)
Canvas.SetLeft(LvlDivider,0)
Canvas.SetTop(LvlDivider,顶部)
下一个
“添加级别
对于a=0到(NumberOfLevels-1)
尺寸LvlWidth为Double=垂直宽度
尺寸层高度为双=垂直高度/层数
双精度尺寸LvlTop=(a*LvlHeight)+(LvlBuffer*LvlHeight)
尺寸LvlBottom为双=LvlHeight-(2*LvlBuffer*LvlHeight)
作为新画布的暗淡LVL容器
LvlContainer.Background=LvlContainerColor
LVL容器。宽度=LVL宽度
LvlContainer.Height=LvlBottom
manRect.Children.Add(LvlContainer)
Canvas.SetLeft(LvlContainer,0)
Canvas.SetTop(LvlContainer,LvlTop)
“添加单元格
对于b=0到(NumberOfCellsPerLevel-1)
Dim CellWidth为Double=LvlWidth/NumberOfCellsPerLevel
Dim CellWidth缓冲为Double=CellWidth-(2*CellBuffer*CellWidth)
尺寸单元高度为双=LvlBottom
将CellTop变暗为双精度=(CellBuffer*CellHeight)
将CellBottom变暗为Double=CellHeight-(2*CellBuffer*CellHeight)
将CellLeft设置为双精度=(b*CellWidth)+(CellBuffer*CellWidth)
将CellContainer设置为新画布
CellContainer.Background=CellContainerColor
CellContainer.Width=CellWidthBuffered
CellContainer.Height=CellBottom
LvlContainer.Children.Add(CellContainer)
Canvas.SetLeft(CellContainer,CellLeft)
Canvas.SetTop(CellContainer,CellTop)
下一个
下一个
'
重置矩阵\单击(按钮\重置矩阵,无)
端接头
私有子CommonCommandBinding_CanExecute(ByVal发送方作为对象,ByVal e作为CanExecuteRoutedEventArgs)
e、 CanExecute=True
端接头
私有子隐藏窗口\单击(ByVal sender作为对象,ByVal e作为RoutedEventArgs)处理按钮\隐藏窗口。单击
HideWindows(False,New StackPanel(){StackPanel_NE,StackPanel_NW,StackPanel_SE,StackPanel_SW})
端接头
私有子ClearWindows_Click(ByVal发件人作为对象,ByVal e作为RoutedEventArgs)处理按钮\u ClearWindows.Click
ClearWindows(新StackPanel(){StackPanel_NE,StackPanel_NW,StackPanel_SE,StackPanel_SW})
端接头
私有子隐藏窗口(ByVal隐藏为布尔值,StackPanels()隐藏为StackPanel)
如果StackPanels.Length=0,则
HideWindows(False,New StackPanel(){StackPanel\u NE,stackp
<Window x:Class="MainWindow"
        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:local="clr-namespace:WpfManipulation2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Image Source="ManipImage.jpg" IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" />
    </Grid>
</Window>
Imports System.Windows.UIElement

Class MainWindow

    Private Sub OnManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
        Dim transformGroup = GetTransformGroup(sender)
        Dim translateTransform = transformGroup.Children.OfType(Of TranslateTransform).First
        Dim rotateTransform = transformGroup.Children.OfType(Of RotateTransform).First
        Dim scaleTransform = transformGroup.Children.OfType(Of ScaleTransform).First
        translateTransform.X = (translateTransform.X + e.DeltaManipulation.Translation.X)
        translateTransform.Y = (translateTransform.Y + e.DeltaManipulation.Translation.Y)
        rotateTransform.Angle = (rotateTransform.Angle + e.DeltaManipulation.Rotation)
        scaleTransform.ScaleY = (scaleTransform.ScaleY * e.DeltaManipulation.Scale.Y)
        scaleTransform.ScaleX = (scaleTransform.ScaleX * e.DeltaManipulation.Scale.X)
    End Sub

    Private Function GetTransformGroup(ByVal sender As Object) As TransformGroup
        Dim element = CType(sender, UIElement)
        element.RenderTransformOrigin = New Point(0.5, 0.5)
        Dim transformGroup = CType(element.RenderTransform, TransformGroup)
        If (transformGroup Is Nothing) Then
            transformGroup = New TransformGroup
            transformGroup.Children.Add(New TranslateTransform)
            transformGroup.Children.Add(New ScaleTransform)
            transformGroup.Children.Add(New RotateTransform)
            element.RenderTransform = transformGroup
        End If

        Return transformGroup
    End Function


End Class
<Window x:Class="WpfTutorialSamples.Common_interface_controls.ToolbarSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ToolbarSample" 
        Top="50" Left="50" Height="500" Width="700">
    <Window.CommandBindings>
        <CommandBinding Command="New" CanExecute="CommonCommandBinding_CanExecute" />
        <CommandBinding Command="Open" CanExecute="CommonCommandBinding_CanExecute" />
        <CommandBinding Command="Save" CanExecute="CommonCommandBinding_CanExecute" />
    </Window.CommandBindings>
    <Window.Resources>
        <MatrixTransform x:Key = "InitialMatrixTransform">
            <MatrixTransform.Matrix>
                <Matrix OffsetX = "0" OffsetY = "0"/>
            </MatrixTransform.Matrix>
        </MatrixTransform>
    </Window.Resources>
    <Grid x:Name="grid_MainWindow" Margin="0,0,0,0">
        <DockPanel>
            <ToolBarTray x:Name="myToolBarTray" DockPanel.Dock="Top" Panel.ZIndex="1">
                <!--
                <ToolBar>
                    <Button Command="New" Content="New" />
                    <Button Command="Open" Content="Open" />
                    <Button Command="Save" Content="Save" />
                </ToolBar>
                <ToolBar>
                    <Button Command="Cut" Content="Cut" />
                    <Button Command="Copy" Content="Copy" />
                    <Button Command="Paste" Content="Paste" />
                </ToolBar>
                -->
                <ToolBar x:Name="myToolBar" Height="30">
                    <Button Name="button_HideWindows" Content="Un/Hide" />
                    <Button Name="button_ClearWindows" Content="Clear" />
                    <Button Name="button_ResetMatrix" Content="Reset" />
                </ToolBar>
            </ToolBarTray>
            <!-- <TextBox AcceptsReturn="True" /> -->
            <!-- <Canvas x:Name="canvas_Main"/> -->
            <Canvas x:Name="canvas_Main" Background="LightPink" >
                <!--
                <Rectangle Name = "manRect" Width = "300" Height = "300"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Top"
                           Margin="0,0,0,0"                           
                IsManipulationEnabled="True" ManipulationDelta="Window_ManipulationDelta"
                RenderTransform = "{StaticResource InitialMatrixTransform}" 
                >
                    <Rectangle.Fill>
                        <SolidColorBrush Color="LightBlue" />
                    </Rectangle.Fill>
                </Rectangle>
                -->
                <Canvas Name = "manRect" Width = "300" Height = "300"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Top"
                           Margin="0,0,0,0"                           
                IsManipulationEnabled="True" ManipulationDelta="Window_ManipulationDelta"
                RenderTransform = "{StaticResource InitialMatrixTransform}" 
                        Background="LightBlue"
                >
                </Canvas>
                <Label x:Name="label_ZoomIn" Content="ZIn" Canvas.Left="330" Canvas.Top="370" Background="LightSkyBlue"/>
                <Label x:Name="label_ZoomOut" Content="ZOut" Canvas.Left="330" Canvas.Top="400" Background="LightSkyBlue"/>
            </Canvas>
        </DockPanel>

        <StackPanel x:Name="stackpanel_NW" Background="LightYellow" HorizontalAlignment="Left" Margin="0,30,0,0" VerticalAlignment="Top"  Height="100" Width="300">
            <Grid x:Name="grid_NW">
                <TextBox x:Name="textbox_NW" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
            </Grid>
        </StackPanel>
        <StackPanel x:Name="stackpanel_NE" Background="LightYellow" HorizontalAlignment="Right" Margin="0,30,0,0" VerticalAlignment="Top"  Height="300" Width="300">
            <Grid x:Name="grid_NE">
                <TextBox x:Name="textbox_NE" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="290" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
            </Grid>
        </StackPanel>
        <StackPanel x:Name="stackpanel_SW" Background="LightYellow" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Bottom"  Height="100" Width="300">
            <Grid x:Name="grid_SW">
                <TextBox x:Name="textbox_SW" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
            </Grid>
        </StackPanel>
        <StackPanel x:Name="stackpanel_SE" Background="LightYellow" HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Bottom"  Height="100" Width="300">
            <Grid x:Name="grid_SE">
                <TextBox x:Name="textbox_SE" Background="LightYellow" BorderThickness="0" AcceptsReturn="True" Height="90" Width="290" Margin="5,5,5,5" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
            </Grid>
        </StackPanel>

    </Grid>
</Window>
'Reference: http://www.wpf-tutorial.com/common-interface-controls/toolbar-control/

Imports System
Imports System.Windows
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Shapes

Namespace WpfTutorialSamples.Common_interface_controls

    Public Class ToolbarSample
        Inherits Window

        Dim CausedByCode As Boolean
        Dim ZoomFactor As Double = 0.1
        Dim ZoomMax As Double = 4.95
        Dim ZoomMin As Double = 0.05
        Dim NumberOfLevels As Integer = 6
        Dim NumberOfCellsPerLevel As Integer = 2
        Dim LvlBuffer As Double = 0.02
        Dim CellBuffer As Double = 0.05
        Dim LvlContainerColor As Brush = Brushes.LightGreen
        Dim CellContainerColor As Brush = Brushes.LightYellow
        Dim LvlDividerColor As Brush = Brushes.Red

        Public Sub New()
            MyBase.New
            InitializeComponent()
        End Sub

        Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
            'HideWindows(False, New StackPanel() {stackpanel_NW, stackpanel_SE, stackpanel_SW})
            HideWindows(True, New StackPanel() {}) 'all
        End Sub

        Private Sub MainWindow_Loaded(sender As Object, e As EventArgs) Handles Me.Loaded
            'add dividers
            For a = 1 To (NumberOfLevels - 1)
                Dim top As Double = a * (manRect.Height / NumberOfLevels)
                Dim LvlDivider As New Canvas
                LvlDivider.Background = LvlDividerColor
                LvlDivider.Width = manRect.Width
                LvlDivider.Height = 0.25
                manRect.Children.Add(LvlDivider)
                Canvas.SetLeft(LvlDivider, 0)
                Canvas.SetTop(LvlDivider, top)
            Next
            'add levels
            For a = 0 To (NumberOfLevels - 1)
                Dim LvlWidth As Double = manRect.Width
                Dim LvlHeight As Double = manRect.Height / NumberOfLevels
                Dim LvlTop As Double = (a * LvlHeight) + (LvlBuffer * LvlHeight)
                Dim LvlBottom As Double = LvlHeight - (2 * LvlBuffer * LvlHeight)
                Dim LvlContainer As New Canvas
                LvlContainer.Background = LvlContainerColor
                LvlContainer.Width = LvlWidth
                LvlContainer.Height = LvlBottom
                manRect.Children.Add(LvlContainer)
                Canvas.SetLeft(LvlContainer, 0)
                Canvas.SetTop(LvlContainer, LvlTop)
                'add cells
                For b = 0 To (NumberOfCellsPerLevel - 1)
                    Dim CellWidth As Double = LvlWidth / NumberOfCellsPerLevel
                    Dim CellWidthBuffered As Double = CellWidth - (2 * CellBuffer * CellWidth)
                    Dim CellHeight As Double = LvlBottom
                    Dim CellTop As Double = (CellBuffer * CellHeight)
                    Dim CellBottom As Double = CellHeight - (2 * CellBuffer * CellHeight)
                    Dim CellLeft As Double = (b * CellWidth) + (CellBuffer * CellWidth)
                    Dim CellContainer As New Canvas
                    CellContainer.Background = CellContainerColor
                    CellContainer.Width = CellWidthBuffered
                    CellContainer.Height = CellBottom
                    LvlContainer.Children.Add(CellContainer)
                    Canvas.SetLeft(CellContainer, CellLeft)
                    Canvas.SetTop(CellContainer, CellTop)
                Next
            Next
            '
            ResetMatrix_Click(button_ResetMatrix, Nothing)
        End Sub

        Private Sub CommonCommandBinding_CanExecute(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = True
        End Sub

        Private Sub HideWindows_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_HideWindows.Click
            HideWindows(False, New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
        End Sub

        Private Sub ClearWindows_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_ClearWindows.Click
            ClearWindows(New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
        End Sub

        Private Sub HideWindows(ByVal Hide As Boolean, StackPanels() As StackPanel)
            If StackPanels.Length = 0 Then
                HideWindows(False, New StackPanel() {stackpanel_NE, stackpanel_NW, stackpanel_SE, stackpanel_SW})
            Else
                For Each s In StackPanels
                    If StackPanels.Length = 4 Then
                        s.Visibility = IIf((s.Visibility = Visibility.Hidden), Visibility.Visible, Visibility.Hidden)
                    Else
                        s.Visibility = IIf(Hide, Visibility.Visible, Visibility.Hidden)
                    End If
                Next
            End If
        End Sub

        Private Sub ClearWindows(StackPanels() As StackPanel)
            For Each s In StackPanels
                Dim g As Grid = (From a In s.Children Where a.GetType = GetType(Grid)
                                 Select TryCast(a, Grid)).FirstOrDefault
                Dim t As TextBox = (From a In g.Children Where a.GetType = GetType(TextBox)
                                    Select TryCast(a, TextBox)).FirstOrDefault
                If s.Visibility = Visibility.Visible Then t.Clear()
            Next
        End Sub

        Private Sub ResetMatrix_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles button_ResetMatrix.Click
            'CenterAboutPoint(New Point(150, 150), e) 'top-left
            CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), False, False, False, e) 'middle of window
        End Sub

        Private Sub label_ZoomIn_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles label_ZoomIn.MouseDown
            CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), True, True, False, e)
        End Sub

        Private Sub label_ZoomOut_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles label_ZoomOut.MouseDown
            CenterAboutPoint(New Point(Me.Width / 2, (Me.Height / 2) - myToolBar.Height), True, False, False, e)
        End Sub

        Private Sub CenterAboutPoint(ByVal p As Point, ByVal JustZoom As Boolean, ByVal ZoomDir As Boolean, ByVal JustTranslate As Boolean, ByVal e As RoutedEventArgs)

            'Dim rectToMove As Rectangle = CType(manRect, Rectangle)
            Dim rectToMove As Canvas = CType(manRect, Canvas)
            Dim rectsMatrix As Matrix = CType(rectToMove.RenderTransform, MatrixTransform).Matrix
            Dim ZoomLevel As Double = rectsMatrix.M11
            Dim transform = TransformToVisual(manRect)
            'textbox_NE.Text = "zoom: " & ZoomLevel & ", width: " & manRect.Width & ", height: " & manRect.Height

            Dim elemPosTopLeft = manRect.TranslatePoint(New Point(0, 0), canvas_Main)
            'textbox_NE.AppendText(vbCrLf & "elemPosTopLeft: " & elemPosTopLeft.ToString)

            Dim elemPosBottomRight = manRect.TranslatePoint(New Point(manRect.ActualWidth, manRect.ActualHeight), canvas_Main)
            'textbox_NE.AppendText(vbCrLf & "elemPosBottomRight: " & elemPosBottomRight.ToString)

            Dim elemPosWidth = (elemPosBottomRight.X - elemPosTopLeft.X) '* -ZoomLevel
            'textbox_NE.AppendText(vbCrLf & "elemPosWidth: " & elemPosWidth.ToString)

            Dim elemPosHeight = (elemPosBottomRight.Y - elemPosTopLeft.Y) '* -ZoomLevel
            'textbox_NE.AppendText(vbCrLf & "elemPosHeight: " & elemPosHeight.ToString)

            Dim elemPosLeft = elemPosTopLeft.X
            'textbox_NE.AppendText(vbCrLf & "elemPosLeft: " & elemPosLeft.ToString)

            Dim elemPosTop = elemPosTopLeft.Y
            'textbox_NE.AppendText(vbCrLf & "elemPosTop: " & elemPosTop.ToString)

            Dim elemPosBottom = elemPosBottomRight.Y
            'textbox_NE.AppendText(vbCrLf & "elemPosBottom: " & elemPosBottom.ToString)

            Dim elemPosRight = elemPosBottomRight.X
            'textbox_NE.AppendText(vbCrLf & "elemPosRight: " & elemPosRight.ToString)

            Dim elemPosCenterX = elemPosLeft + (elemPosWidth / 2)
            'textbox_NE.AppendText(vbCrLf & "elemPosCenterX: " & elemPosCenterX.ToString)

            Dim elemPosCenterY = elemPosTop + (elemPosHeight / 2)
            'textbox_NE.AppendText(vbCrLf & "elemPosCenterY: " & elemPosCenterY.ToString)

            'offsets from point
            Dim elemPosLeftOffset = p.X - elemPosCenterX
            'textbox_NE.AppendText(vbCrLf & "elemPosLeftOffset: " & elemPosLeftOffset.ToString)

            Dim elemPosTopOffset = p.Y - elemPosCenterY
            'textbox_NE.AppendText(vbCrLf & "elemPosTopOffset: " & elemPosTopOffset.ToString)

            'scale
            If JustTranslate = False Then
                If JustZoom = False Then
                    If ZoomLevel <> 1 Then
                        rectsMatrix.ScaleAt((1 / ZoomLevel), (1 / ZoomLevel), elemPosCenterX, elemPosCenterY)
                    End If
                Else
                    Dim NewZoomLevel = IIf(ZoomDir = True, (1 + ZoomFactor), (1 - ZoomFactor))
                    'textbox_NE.AppendText(vbCrLf & "NewZoomLevel: " & NewZoomLevel.ToString)
                    If ((ZoomLevel * NewZoomLevel) >= ZoomMin) And ((ZoomLevel * NewZoomLevel) <= ZoomMax) Then
                        rectsMatrix.ScaleAt(NewZoomLevel, NewZoomLevel, elemPosCenterX, elemPosCenterY)
                    End If
                End If
            End If

            'translate
            If JustZoom = False Then
                rectsMatrix.Translate(elemPosLeftOffset, elemPosTopOffset)
            End If
            'transform
            rectToMove.RenderTransform = New MatrixTransform(rectsMatrix)
            If Not IsNothing(e) Then e.Handled = True
        End Sub

        Private Sub Window_ManipulationStarting(ByVal sender As Object, ByVal e As ManipulationStartingEventArgs)
            e.ManipulationContainer = Me
            e.Handled = True
        End Sub

        Private Sub Window_ManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
            'Reference: https://www.tutorialspoint.com/wpf/wpf_multi_touch.htm
            'Dim rectToMove As Rectangle = CType(e.OriginalSource, Rectangle)
            Dim rectToMove As Canvas = CType(e.OriginalSource, Canvas)
            Dim rectsMatrix As Matrix = CType(rectToMove.RenderTransform, MatrixTransform).Matrix
            Dim ZoomLevel As Double = rectsMatrix.M11
            'scale
            Dim scale As Double = (e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2
            rectsMatrix.ScaleAtPrepend(scale, scale, e.ManipulationOrigin.X, e.ManipulationOrigin.Y)
            'translate
            If CausedByCode = False AndAlso (Math.Abs(e.DeltaManipulation.Translation.X) > 1 Or Math.Abs(e.DeltaManipulation.Translation.Y) > 1) Then
                rectsMatrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y)
                CausedByCode = True
            Else
                CausedByCode = False
            End If
            'apply transformation
            If (rectsMatrix.M11 >= ZoomMin) And (rectsMatrix.M11 <= ZoomMax) Then
                rectToMove.RenderTransform = New MatrixTransform(rectsMatrix)
            End If
            Dim containingRect As Rect = New Rect(CType(e.ManipulationContainer, FrameworkElement).RenderSize)
            Dim shapeBounds As Rect = rectToMove.RenderTransform.TransformBounds(New Rect(rectToMove.RenderSize))
            If (e.IsInertial AndAlso Not containingRect.Contains(shapeBounds)) Then
                e.Complete()
            End If

            e.Handled = True
        End Sub

        Private Sub Window_InertiaStarting(ByVal sender As Object, ByVal e As ManipulationInertiaStartingEventArgs)
            e.TranslationBehavior.DesiredDeceleration = (10 * (96 / (1000 * 1000))) 'inches per second squared
            e.ExpansionBehavior.DesiredDeceleration = (0.1 * (96 / (1000 * 1000))) 'inches per second squared
            e.RotationBehavior.DesiredDeceleration = (720 / (1000 * 1000)) 'degrees per second squared
            e.Handled = True
        End Sub

    End Class

End Namespace
<Image Source="https://placehold.it/200x200" IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" />
private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
    var transformGroup = GetTransformGroup(sender);
    var translateTransform = transformGroup.Children.OfType<TranslateTransform>().First();
    var rotateTransform = transformGroup.Children.OfType<RotateTransform>().First();
    var scaleTransform = transformGroup.Children.OfType<ScaleTransform>().First();

    translateTransform.X += e.DeltaManipulation.Translation.X;
    translateTransform.Y += e.DeltaManipulation.Translation.Y;
    rotateTransform.Angle += e.DeltaManipulation.Rotation;
    scaleTransform.ScaleY *= e.DeltaManipulation.Scale.Y;
    scaleTransform.ScaleX *= e.DeltaManipulation.Scale.X;
}

private TransformGroup GetTransformGroup(object sender)
{
    var element = sender as UIElement;

    element.RenderTransformOrigin = new Point(.5, .5);

    var transformGroup = element.RenderTransform as TransformGroup;

    if (transformGroup == null)
    {
        transformGroup = new TransformGroup();
        transformGroup.Children.Add(new TranslateTransform());
        transformGroup.Children.Add(new ScaleTransform());
        transformGroup.Children.Add(new RotateTransform());

        element.RenderTransform = transformGroup;
    }

    return transformGroup;
}