ToolWindow does not allow for manipulation events

Docking/MDI for WPF Forum

Posted 3 years ago by Shawn Kendrot
Version: 16.1.0633
Platform: .NET 4.5
Environment: Windows 10 (64-bit)
Avatar

I have a ToolWindow that acts as a image viewer. You can zoom/pan around the image. Pinch functionality does not work within the ToolWindow, but does within a Workspace. Repo steps:

  1. Create a new WPF application
  2. Add a reference to docking tools
  3. Add the following in the MainWindow
    <docking:DockSite >
        <docking:SplitContainer>
            <docking:Workspace>
    
            </docking:Workspace>
            <docking:ToolWindowContainer>
                <docking:ToolWindow Title="Image Gallery">
                    <Border Background="Black"
                            ClipToBounds="True"
                            IsManipulationEnabled="True"
                            ManipulationDelta="Border_ManipulationDelta"
                            MouseMove="Border_MouseMove"
                            MouseLeftButtonDown="Border_MouseLeftButtonDown"
                            MouseLeftButtonUp="Border_MouseLeftButtonUp"
                            MouseWheel="Border_MouseWheel">
                        <Image x:Name="Image" RenderTransformOrigin=".5,.5"/>
                    </Border>
                </docking:ToolWindow>
            </docking:ToolWindowContainer>
        </docking:SplitContainer>
    </docking:DockSite>
  4. Add the follow in the code behind
    private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Manipulation: " + e.DeltaManipulation.Translation);
        System.Diagnostics.Debug.WriteLine("        Translation.X: " + e.DeltaManipulation.Translation.X);
        System.Diagnostics.Debug.WriteLine("        Translation.Y: " + e.DeltaManipulation.Translation.Y);
        System.Diagnostics.Debug.WriteLine("              Scale.X: " + e.DeltaManipulation.Scale.X);
        System.Diagnostics.Debug.WriteLine("              Scale.Y: " + e.DeltaManipulation.Scale.Y);
    
        Border b = (Border)sender;
        MatrixTransform mt = (MatrixTransform)Image.RenderTransform;
        Matrix m = mt.Matrix;
        m.OffsetX += e.DeltaManipulation.Translation.X;
        m.OffsetY += e.DeltaManipulation.Translation.Y;
        m.M11 *= e.DeltaManipulation.Scale.X;
        m.M22 *= e.DeltaManipulation.Scale.Y;
        m = FitMatrixToBounds(m, new Size(Image.ActualWidth, Image.ActualHeight), new Size(b.ActualWidth, b.ActualHeight));
    
        Image.RenderTransform = new MatrixTransform(m);
    }
    
    private void Border_MouseMove(object sender, MouseEventArgs e)
    {
        Border b = (Border)sender;
        if (b.IsMouseCaptured)
        {
            Point p = e.GetPosition(b);
            MatrixTransform mt = (MatrixTransform)Image.RenderTransform;
            Matrix m = mt.Matrix;
    
            if (m.M11 != 1)
            {
                m.OffsetX += p.X - _dragOrigin.X;
                m.OffsetY += p.Y - _dragOrigin.Y;
                m = FitMatrixToBounds(m, new Size(Image.ActualWidth, Image.ActualHeight), new Size(b.ActualWidth, b.ActualHeight));
    
                Image.RenderTransform = new MatrixTransform(m);
            }
            _dragOrigin = p;
        }
    }
    
    private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if(e.ClickCount % 2 == 0)
        {
            Border_MouseWheel(sender, new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, 1));
            return;
        }
        Border b = (Border)sender;
        _dragOrigin = e.GetPosition(b);
        b.CaptureMouse();
    }
    
    private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        Border b = (Border)sender;
        b.ReleaseMouseCapture();
    }
    
    private void Border_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        Border b = (Border)sender;
    
        double zoom = e.Delta > 0 ? 2 : 0.5;
        MatrixTransform mt = (MatrixTransform)Image.RenderTransform;
        Matrix m = mt.Matrix;
    
        m.M11 *= zoom;
        m.M22 *= zoom;
    
        m = FitMatrixToBounds(m, new Size(Image.ActualWidth, Image.ActualHeight), new Size(b.ActualWidth, b.ActualHeight));
    
        Image.RenderTransform = new MatrixTransform(m);
    }
    
    private Matrix FitMatrixToBounds(Matrix m, Size size, Size bounds)
    {
        if (m.M11 < 1)
        {
            return Matrix.Identity;
        }
        if (m.M11 == 1)
        {
            m.OffsetX = m.OffsetY = 0;
        }
        else
        {
            var maxWidth = Math.Abs(((size.Width * m.M11) - bounds.Width) / 2);
            var maxHeight = Math.Abs(((size.Height * m.M22) - bounds.Height) / 2);
            if (Math.Abs(m.OffsetX) > maxWidth)
            {
                if (m.OffsetX > 0) m.OffsetX = maxWidth;
                else m.OffsetX = -maxWidth;
            }
            if (Math.Abs(m.OffsetY) > maxHeight)
            {
                if (m.OffsetY > 0) m.OffsetY = maxHeight;
                else m.OffsetY = -maxHeight;
            }
        }
        return m;
    }
    
  5. Make sure to set the source for the Image
  6. Run the application.
  7. Use the mouse to scroll in out of the image. -- Should work fine
  8. Use the mouse to move the image around (provided it is zoomed in) -- should work fine
  9. Using a touch monitor pan the image (provided it is zoomed in) -- should work fine
  10. Using a touch monitor, pinch to zoom in/out of the image. -- will not work
  11. Move the Border element into the Workspace and repeat steps 6-10. Everything should work fine.

I'm pretty sure this worked before upgrading the docking tools (previous framework)

Comments (4)

Answer - Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Shawn,

Thanks for reporting this.  We've fixed it for the upcoming maintenance release.  Please email us if you'd like to try the fix in a preview build.


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

When will the maintainance release be available publicly?

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

It's about ready but we're having trouble getting the controls to show in the VS 15 (vNext) Toolbox.  We're working with Microsoft to try and sort out what has changed on their end before releasing.


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

I can confirm it is fixed with version 16.1.635

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.