#

Download:

Datei 1: wpf_snapin_Files.zip

WPF: Snap Next Lines

 

Das folgende Code Beispiel enthält eine WPF Anwendung, bei welcher die beweglichen Elemente sich stets an die anderen Elemente andocken.

Der C# Code basiert darauf, dass wenn eine Ecke eines Elements verschoben wird, die neue Position in der Top und Left Position zu allen anderen UIElementen gegengeprüft wird.

Sobald der Abstand ein Minimum unterschreitet, wird das Element angedockt.

 

 

 

 

 

 

C# Code zum prüfen, ob eine horizontale Position  oder vertikale Position im Rahmen eines anderen Elements liegt.

 

        double dbl_SnapNext = 0;

        private double snap_Next_X(double check_X)

        {

            foreach (UIElement element in CanvasMain.Children)

            {

                if (element.GetType() == typeof(UcPanel))

                {

                    UcPanel loop_panel = element as UcPanel;

                    if (loop_panel != sizing_Panel)

                    {

                        double pos_loop_x = -this.TranslatePoint(new Point(0, 0), loop_panel).X;

                        //< check top >

                        if (pos_loop_x != check_X) if (Math.Abs(pos_loop_x - check_X) < int_SnapRange)

                            { return pos_loop_x; }

                        //</ check top >

 

                        //< check bottom >

                        if ((pos_loop_x + loop_panel.ActualWidth) != check_X)

                        {

                            if (Math.Abs((pos_loop_x + loop_panel.ActualWidth) - check_X) < int_SnapRange)

                            { return (pos_loop_x + loop_panel.ActualWidth); }

                        }

                        //< check bottom >

                    }

                }

            }

            return -1;

        }

 

        private double snap_Next_Y(double check_Y)

        {

            foreach (UIElement element in CanvasMain.Children)

            {

                if (element.GetType() == typeof(UcPanel))

                {

                    UcPanel loop_panel = element as UcPanel;

                    if (loop_panel!=sizing_Panel )

                    {

                        double pos_loop_y = - this.TranslatePoint(new Point(0, 0), loop_panel).Y;

                        //< check top >

                        if (pos_loop_y != check_Y) if (Math.Abs(pos_loop_y - check_Y) < int_SnapRange)

                            { return pos_loop_y; }

                        //</ check top >

 

                        //< check bottom >

                        if ((pos_loop_y + loop_panel.ActualHeight) != check_Y)

                        {

                            if (Math.Abs((pos_loop_y + loop_panel.ActualHeight) - check_Y) < int_SnapRange)

                            { return (pos_loop_y + loop_panel.ActualHeight); }

                        }

                        //< check bottom >

                    }

                }

            }

            return -1;

        }

 

 

 

C# Sizing Code.

 

Hier wird eine der 4 veränderbaren Ecken des Child-Elements (UserControl) oder die Titlebar verschoben.

Vor dem verschieben der Position wird geprüft, ob ein Snap-In zu einer horizontalen oder vertikalen Linie aller anderen Elemente vorliegt.

 

        private void set_Sizing(object sender, MouseEventArgs e)

        {

            //-------------< sizing_Cols_And_Rows() >-------------

            if (isSizing == false) return;

            //< check >

            if (sizing_EdgeType < 0) return;

            if (sizing_Panel == null) return;

            //</ check >

 

            if (e.LeftButton != MouseButtonState.Pressed)

            {

                isSizing = false;

            }

            else

            {

                //------< MouseButtonState.Pressed >------

                //< mouse position >

                Point mouse_point = e.GetPosition(this);

                double mouse_x = mouse_point.X;

                double mouse_y = mouse_point.Y;

                //</ mouse position >

 

                //--< get Position >--

                Point position = this.TranslatePoint(new Point(0, 0), sizing_Panel);

                double pos_X = -position.X;

                double pos_Y = -position.Y;

                //--</ get Position >--

 

                double diff_X = (pos_X - mouse_x);

                double diff_Y = (pos_Y - mouse_y);

 

                if (sizing_EdgeType == (int)EdgeTypes.TopMove)

                {

                    //----< sizing Move >----

                    double new_Left = mouse_x - sizing_Offset_X;

                    double new_Top = mouse_y - sizing_Offset_Y;

 

                    //--< Snap >--

                    //< snap Left+Top >

                    if (new_Left < int_SnapRange) { new_Left = 0; }

                    if (new_Top < int_SnapRange) { new_Top = 0; }

                    //</ snap Left+Top >

 

                    //< snap adjust Right+Bottom >

                    if (CanvasMain.ActualWidth - (new_Left + sizing_Panel.ActualWidth) < int_SnapRange) { new_Left = CanvasMain.ActualWidth - sizing_Panel.ActualWidth; }

                    if (CanvasMain.ActualHeight - (new_Top + sizing_Panel.ActualHeight) < int_SnapRange) { new_Top = CanvasMain.ActualHeight - sizing_Panel.ActualHeight; }

                    //</ snap adjust Right+Bottom >

 

                    //--< snap next >--

                    //< snap next vertical >

                    if (new_Left != 0)

                    {

                        dbl_SnapNext = snap_Next_X(new_Left);

                        if (dbl_SnapNext > 0)

                        {

                            new_Left = dbl_SnapNext;

                        }

                        else

                        {

                            dbl_SnapNext = snap_Next_X(new_Left + sizing_Panel.ActualWidth);

                            if (dbl_SnapNext > 0)

                            { new_Left = dbl_SnapNext - sizing_Panel.ActualWidth; }

                        }

                    }

                    //</ snap next vertical >

 

                    //< snap next horizontal >

                    if (new_Top != 0)

                    {

                        dbl_SnapNext = snap_Next_Y(new_Top);

                        if (dbl_SnapNext > 0)

                        {

                            new_Top = dbl_SnapNext;

                        }

                        else

                        {

                            dbl_SnapNext = snap_Next_Y(new_Top + sizing_Panel.ActualHeight);

                            if (dbl_SnapNext > 0)

                            { new_Top = dbl_SnapNext - sizing_Panel.ActualHeight; }

                        }

                    }

                    //</ snap next horizontal >

                    //--</ snap next >--

 

                    //-</ Snap >--

 

                    //< set >

                    if (new_Left >= 0) Canvas.SetLeft(sizing_Panel, new_Left);

                    if (new_Top >= 0) Canvas.SetTop(sizing_Panel, new_Top);

                    //</ set >

 

                    //----</ sizing Move >----

                }

                else

                {

                    //-------------< sizing >--------------

                    if ((sizing_EdgeType == (int)EdgeTypes.TopLeft) || (sizing_EdgeType == (int)EdgeTypes.BottomLeft))

                    {

                        //----< sizing Left >----

                        double new_Left = mouse_x;

                        double new_Width = (sizing_Panel.ActualWidth) + diff_X;

 

                        //< snap Left >

                        if (new_Left < int_SnapRange) { new_Left = 0; new_Width = pos_X + sizing_Panel.ActualWidth; }

                        //</ snap Left >

 

                        //< snap next vertical >

                        if (new_Left != 0)

                        {

                            dbl_SnapNext = snap_Next_X(new_Left);

                            if (dbl_SnapNext > 0)

                            {

                                new_Left = dbl_SnapNext;

                                new_Width = (pos_X-new_Left) + sizing_Panel.ActualWidth;

                            }

                        }

                        //</ snap next vertical >

 

 

 

                        //< set Left+Width >

                        if (new_Left >= 0) Canvas.SetLeft(sizing_Panel, new_Left);

                        if (new_Width >= 0) sizing_Panel.Width = new_Width;

                        //</ set Left+width >

 

                        //----</ sizing Left >----

                    }

 

                    if ((sizing_EdgeType == (int)EdgeTypes.TopLeft) || (sizing_EdgeType == (int)EdgeTypes.TopRight))

                    {

                        //----< sizing Top >----

                        double new_Top = mouse_y;

                        double new_Height = (sizing_Panel.ActualHeight) + diff_Y;

 

                        //< snap Top >

                        if (new_Top < int_SnapRange) { new_Top = 0; new_Height = pos_Y +sizing_Panel.ActualHeight;  }

                        //</ snap Top >

 

                        //< snap next vertical >

                        if (new_Top != 0)

                        {

                            dbl_SnapNext = snap_Next_Y(new_Top);

                            if (dbl_SnapNext > 0)

                            {

                                new_Top = dbl_SnapNext;

                                new_Height = (pos_Y - new_Top) + sizing_Panel.ActualHeight;

                            }

                        }

                        //</ snap next vertical >

 

                        //< set Top+Height>

                        if (new_Top >= 0) Canvas.SetTop(sizing_Panel, new_Top);

                        if (new_Height >= 0) sizing_Panel.Height = new_Height;

                        //</ set Top+Height >

 

 

                        //----</ sizing Top >----

                    }

 

                    if ((sizing_EdgeType == (int)EdgeTypes.TopRight) || (sizing_EdgeType == (int)EdgeTypes.BottomRight))

                    {

                        //----< sizing Right >----

                        double new_Width = mouse_x - pos_X;

                        

                        //< snap rigth >

                        if (CanvasMain.ActualWidth - (new_Width + pos_X ) < int_SnapRange) { new_Width = CanvasMain.ActualWidth - pos_X ; }

                        //</ snap rigth >

 

                        //< snap next vertical >

                        if (new_Width != 0)

                        {

                            dbl_SnapNext = snap_Next_X(pos_X+new_Width);

                            if (dbl_SnapNext > 0)

                            {

                                new_Width = dbl_SnapNext- pos_X;                               

                            }

                        }

                        //</ snap next vertical >

 

                        //< set width >

                        if (new_Width >= 0) sizing_Panel.Width = new_Width;

                        //</ set width >

 

                        //----</ sizing Right >----

                    }

 

                    if ((sizing_EdgeType == (int)EdgeTypes.BottomLeft) || (sizing_EdgeType == (int)EdgeTypes.BottomRight))

                    {

                        //----< sizing Bottom >----

                        double new_Height = mouse_y - pos_Y;

 

                        //< snap rigth >

                        if (CanvasMain.ActualHeight - (new_Height + pos_Y) < int_SnapRange) { new_Height = CanvasMain.ActualHeight - pos_Y; }

                        //</ snap rigth >

 

                        //< snap next vertical >

                        if (new_Height != 0)

                        {

                            dbl_SnapNext = snap_Next_Y(pos_Y + new_Height);

                            if (dbl_SnapNext > 0)

                            {

                                new_Height = dbl_SnapNext - pos_Y;

                            }

                        }

                        //</ snap next vertical >

 

                        //< set width >

                        if (new_Height >= 0) sizing_Panel.Height = new_Height;

                        //</ set width >

 

                        //----</ sizing Bottom >----

                    }

                    //-------------</ sizing >--------------

                }

 

 

                //------</ MouseButtonState.Pressed >------

            }

 

            //-------------</ sizing_Cols_And_Rows() >-------------

        }

 

 

 

        #region mouse dragging

        //-------------< MouseMove() >-------------

        public Boolean isSizing = false;

        public int sizing_EdgeType = 0;

        public double sizing_Offset_X = 0;

        public double sizing_Offset_Y = 0;

        public UcPanel sizing_Panel = null;

        public Border sizing_Edge = null;

 

        private int int_SnapRange = 40;

       

        enum EdgeTypes

        {

            TopMove = 0,

            TopLeft = 1,

            TopRight = 2,

            BottomLeft = 3,

            BottomRight = 4

        }

 

        double dbl_SnapNext = 0;

 

 

Xaml Code des MainWindow

<Window x:Class="wpf_Rectangles_Adjusting.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:uc="clr-namespace:wpf_Rectangles_Adjusting._UserControls"       

        xmlns:local="clr-namespace:wpf_Rectangles_Adjusting"

        mc:Ignorable="d"

        Title="MainWindow" Height="350" Width="525" AllowsTransparency="False" Background="White" WindowStyle="SingleBorderWindow">

    <Canvas x:Name="CanvasMain" Background="White" MouseMove="CanvasMain_MouseMove" MouseUp="CanvasMain_MouseUp">

        <uc:UcPanel Width="100" Height="100" Canvas.Left="110" Canvas.Top="40"></uc:UcPanel>

 

        <uc:UcPanel Width="100" Height="100" Canvas.Left="240" Canvas.Top="150"></uc:UcPanel>

    </Canvas>

    </Window>

 

 

 

UserControl

 

XAML Code des UserControls, welches die beweglichen Elemente darstellt

<UserControl x:Class="wpf_Rectangles_Adjusting._UserControls.UcPanel"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

             xmlns:local="clr-namespace:wpf_Rectangles_Adjusting._UserControls"

             mc:Ignorable="d"

             d:DesignHeight="300" d:DesignWidth="300" IsHitTestVisible="True" >

    <Grid >

        <Border BorderThickness="1" BorderBrush="Black" ></Border>

 

        <Border  x:Name="recTop" HorizontalAlignment="Stretch"  VerticalAlignment="Top"  Height="10" Background ="LightGray"  Opacity="0.5" MouseDown="recTop_MouseDown" MouseEnter="recTop_MouseEnter" MouseLeave="rec_MouseLeave">

        </Border>

 

        <Border  x:Name="recLeftTop" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="10" Height="10" Background ="Gray" Opacity="0.1" MouseDown="recLeftTop_MouseDown" MouseEnter="recLeftTop_MouseEnter" MouseLeave="rec_MouseLeave">

        </Border>

        <Border  x:Name="recRightTop" HorizontalAlignment="Right" VerticalAlignment="Top" Width="10" Height="10" Background ="Gray" Opacity="0.1" MouseDown="recRightTop_MouseDown" MouseEnter="recRightTop_MouseEnter" MouseLeave="rec_MouseLeave" >

        </Border>

        <Border  x:Name="recLeftBottom" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="10" Height="10" Background ="Gray" Opacity="0.1" MouseDown="recLeftBottom_MouseDown" MouseEnter="recLeftBottom_MouseEnter" MouseLeave="rec_MouseLeave">

        </Border>

        <Border  x:Name="recRightBottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="10" Height="10" Background ="Gray" Opacity="0.2" MouseDown="recRightBottom_MouseDown" MouseEnter="recRightBottom_MouseEnter" MouseLeave="rec_MouseLeave"  >

        </Border>

    </Grid>

</UserControl>

 

 

Mobile

.

soap2day