简体   繁体   中英

How can I stop a moving user control from intersecting with other user controls of the same type?

Hello :) I'm working in WPF, my main window is a canvas. I have created a user control called Country , which can be moved along the main window with the mouse:

public partial class Country : UserControl
{
    private Point position = new Point(0, 0);
    private Point mousePosition = new Point(0, 0);
    protected Boolean isDragging;
    private Double prevX, prevY;
    public static List<Country> list = new List<Country>();
    public static int num = 1;
    private string riddle;

    public Country()
    {
        InitializeComponent();
        this.Height = 100;
        this.Width = 100;
        this.Background = Brushes.Red;
        this.Content = "country" + num;
        num++;
        position = new Point(Canvas.GetLeft(this), Canvas.GetTop(this));
        this.MouseLeftButtonDown += new MouseButtonEventHandler(Control_MouseLeftButtonDown);
        this.MouseLeftButtonUp += new MouseButtonEventHandler(Control_MouseLeftButtonUp);
        this.MouseMove += new MouseEventHandler(Control_MouseMove);
        list.Add(this);
    }

    private void Control_MouseLeftButtonDown(Object sender, MouseButtonEventArgs e)
    {
        isDragging = true;
        var draggableControl = (sender as UserControl);
        mousePosition = e.GetPosition(Parent as UIElement);
        draggableControl.CaptureMouse();
    }

    private void Control_MouseLeftButtonUp(Object sender, MouseButtonEventArgs e)
    {
        isDragging = false;
        var draggable = (sender as UserControl);
        var transform = (draggable.RenderTransform as TranslateTransform);
        if (transform != null)
        {
            prevX = transform.X;
            prevY = transform.Y;
        }
        draggable.ReleaseMouseCapture();
    }

    private void Control_MouseMove(Object sender, MouseEventArgs e)
    {
                var draggableControl = (sender as UserControl);
                if (isDragging && draggableControl != null)
                {
                    var currentPosition = e.GetPosition(Parent as UIElement);
                    var transform = (draggableControl.RenderTransform as TranslateTransform);
                    if (transform == null)
                    {
                        transform = new TranslateTransform();
                        draggableControl.RenderTransform = transform;
                    }
                    double aX = transform.X;
                    double aY = transform.Y;
                    transform.X = (currentPosition.X - mousePosition.X);
                    transform.Y = (currentPosition.Y - mousePosition.Y);
                    if (prevX > 0)
                    {
                        transform.X += prevX;
                        transform.Y += prevY;
                    }
                }
            }
        }

This is the xaml code:

<UserControl x:Class="WpfApplication7.Country"
         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:WpfApplication7"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid Width="100" Height="100" Background="Red">

</Grid>
</UserControl>

I've been trying to prevent instances of Country from intersecting with each other, that is - if I have multiple countries in the MainWindow, and I'm moving a country and it's about to intersect with another country, then the moving country will stop, or go back, or something like that. Unfortunately all the ideas I had in mind failed. Should I do something in the MainWindow, perhaps? I would be really glad if someone can offer a solution or an insight to this.

Help will be much appreciated

From the user's expirience point the better solution is not stop drugging but just to indicate to the user this operation cannot be performed. I would suggest something like cursor changing (like in standard Windows drag-n-drop applications) or color changing for an objects beneath your drugging one (this approach is used in some games) or both of them.

I think, you should have an event in your Country class and an appropriate event handler in the main window. So you can track any countries movement and react in easy way.

Add a public rect variable to country. When you add them to the canvas add to a list in mainwindow. Handle previewmousemove etc on the canvas to move them. When you drag, update the rect using the current top and left, actualheight and width. Iterate through your list of countries. Use rect.intersectsWith to see if they will overlap in the new position. If they do then stop dragging and don't move the control.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM