实现WPF Snap Grid

use*_*816 5 wpf xaml

我正在尝试使用WPF和画布实现捕捉网格.我在想我的数学是关闭的,因为UIElement不会在后台捕捉到网格.下面是我用来创建网格的xaml以及我用来尝试将UIElement捕捉到最近网格线的方法.一旦触发鼠标按钮事件,就会触发使用的方法.如果这不是正确的WPF方法,有人能指出我正确的方向吗?

XAML

 <Border x:Name="dragBorder" 
            BorderBrush="Black"
            BorderThickness="1"
            Margin="5"
            CornerRadius="3">
        <Canvas x:Name="dragCanvas"
                            AllowDragging="true"
                            AllowDragOutOfView="False"
                            Height="{Binding ElementName=dragBorder, Path=ActualHeight}"
                            Width="{Binding ElementName=dragBorder, Path=ActualWidth}">
            <Canvas.Background>
                <VisualBrush TileMode="Tile"
                             Viewport="0,0,16,16"
                             ViewportUnits="Absolute"
                             Viewbox="0,0,16,16"
                             ViewboxUnits="Absolute">
                    <VisualBrush.Visual>
                        <Ellipse Fill="#FF000000"
                                 Width="2"
                                 Height="2" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Canvas.Background>
        </Canvas>
    </Border>
Run Code Online (Sandbox Code Playgroud)

方法

private void SnapToGrid(UIElement element)
    {
        double xSnap = (Canvas.GetLeft(element) / gridWidth) * gridWidth;
        double ySnap = (Canvas.GetTop(element) / gridWidth) * gridWidth;

        Canvas.SetLeft(element, xSnap);
        Canvas.SetTop(element, ySnap);

        double tempX = Canvas.GetLeft(element);
        double tempY = Canvas.GetTop(element);
    }   
Run Code Online (Sandbox Code Playgroud)

Ada*_*lls 7

你的问题是你的功能实际上没有做任何事情.你除以网格大小然后乘以网格大小,所以实际上你什么都不做(2*16/16 = 2).您需要使用的是模数%运算符,并根据与网格大小的距离调整x/y位置.

这是一个工作函数,如果更靠近左/顶部网格线,则向左/向上捕捉,否则向右/向下捕捉:

private void SnapToGrid( UIElement element ) {
    double xSnap = Canvas.GetLeft( element ) % GRID_SIZE;
    double ySnap = Canvas.GetTop( element ) % GRID_SIZE;

    // If it's less than half the grid size, snap left/up 
    // (by subtracting the remainder), 
    // otherwise move it the remaining distance of the grid size right/down
    // (by adding the remaining distance to the next grid point).
    if( xSnap <= GRID_SIZE / 2.0 )
        xSnap *= -1;
    else
        xSnap = GRID_SIZE - xSnap;
    if( ySnap <= GRID_SIZE / 2.0 )
        ySnap *= -1;
    else
        ySnap = GRID_SIZE - ySnap;

    xSnap += Canvas.GetLeft( element );
    ySnap += Canvas.GetTop( element );

    Canvas.SetLeft( element, xSnap );
    Canvas.SetTop( element, ySnap );
}
Run Code Online (Sandbox Code Playgroud)