自分用バックアップ2020_01_15_18_00

とりあえずバックアップしておきます。

<Window x:Class="WpfApp17.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:WpfApp17"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <DockPanel>
        <Button DockPanel.Dock="Top" Content="button1" Height="50" />
        <Button DockPanel.Dock="Bottom" Content="button1" Height="50" />
        <Button DockPanel.Dock="Left" Content="button1" Width="50" />
        <Button DockPanel.Dock="Right" Content="button1" Width="50" />
        <Canvas SnapsToDevicePixels="True">

            <Canvas.Background>
                <VisualBrush TileMode="Tile" Viewbox="0,0,100,100" ViewboxUnits="Absolute" Viewport="0,0,100,100" ViewportUnits="Absolute">
                    <VisualBrush.Visual>
                        <Rectangle Stroke="DarkGray" StrokeThickness="1" Width="100" Height="100" StrokeDashArray="5 5" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Canvas.Background>
            
            <Thumb Canvas.Top="0" Canvas.Left="0" DragDelta="Thumb_DragDelta">
                <Thumb.Template>
                    <ControlTemplate>
                        <Grid>
                            <Rectangle Width="100" Height="100" Stroke="Blue" StrokeThickness="1" Fill="AliceBlue" />
                            <TextBlock Text="textBlock1" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>
            
        </Canvas>
    </DockPanel>

</Window>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace WpfApp17
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var target = sender as Thumb;
            if (target is null)
                return;
            
            var canvas1 = target.Parent as Canvas;
            if (canvas1 is null)
                return;

            // 現在 Canvas 上にいる位置のうち左上の位置(X, Y) に、移動量を加えて、
            // 実際に移動させるかどうか(Canvas.SetXxx() を呼ぶかどうか)を判定する
            var x = Canvas.GetLeft(target) + e.HorizontalChange;
            var y = Canvas.GetTop(target) + e.VerticalChange;
            
            // 画面の端を超えそうになったら、吸着させて飛び越えさせない
            if (x < 0)
            {
                Canvas.SetLeft(target, 0);
                return;
            }

            if (y < 0)
            {
                Canvas.SetTop(target, 0);
                return;
            }

            // 移動量制限なしの場合の幅チェック
            //if (canvas1.ActualWidth < x + target.ActualWidth)
            //{
            //    Canvas.SetLeft(target, canvas1.ActualWidth - target.ActualWidth);
            //    return;
            //}

            //if (canvas1.ActualHeight < y + target.ActualHeight)
            //{
            //    Canvas.SetTop(target, canvas1.ActualHeight - target.ActualHeight);
            //    return;
            //}


            // 100px 単位の移動に制限させたい
            x = Math.Round(x / 100.0) * 100;
            y = Math.Round(y / 100.0) * 100;
            
            // 調整後の値で再度幅制限チェック
            if (canvas1.ActualWidth < x + target.ActualWidth)
            {
                var maxWidth = Math.Truncate(canvas1.ActualWidth / 100) * 100;
                Canvas.SetLeft(target, maxWidth - target.ActualWidth);
                return;
            }

            if (canvas1.ActualHeight < y + target.ActualHeight)
            {
                var maxHeight = Math.Truncate(canvas1.ActualHeight / 100) * 100;
                Canvas.SetTop(target, maxHeight - target.ActualHeight);
                return;
            }

            // 真ん中あたりの位置の場合
            Canvas.SetLeft(target, x);
            Canvas.SetTop(target, y);
        }
    }
}