C# привязать объект A к краю объекта B

Я пытаюсь написать приложение на C#, которое позволит пользователю привязать один объект (допустим, они являются прямоугольниками разного размера, с различными определяемыми пользователем текстом и другими атрибутами на каждом) к краю другого.

Я знаю, что это можно сделать относительно легко, используя JavaScript и FabricJS (см. Этот пример из другого вопроса здесь), однако я не знаю, как бы я достиг того же результата в C#.

Это то, что я могу достичь с помощью "стандартной" библиотеки C#? Если так, то как? Или мне нужно использовать стороннюю библиотеку или движок?

Заранее спасибо!

DS.

1 ответ

Приведенный ниже пример кода иллюстрирует, что элемент управления StackPanel проверяет объект, который перемещается, чтобы определить, находится ли он на определенном расстоянии от какого-либо другого объекта, и сдвигает этот объект так, что он примыкает к другому объекту. Простой тест приведенного ниже кода демонстрирует, что невозможно перетащить один объект так, чтобы он перекрывал другой, и невозможно перетащить объект так, чтобы он не примыкал к другому. Функциональность, которая позволяет пользователю привязывать один объект... к краю другого, обеспечивается библиотекой WPF и, в частности, элементом управления StackPanel.

В духе общего характера вопроса OP, я также укажу, что WPF предоставляет надежную библиотеку элементов управления и функций, которые позволяют разработчику проверять близость одного элемента управления к другому и упорядочивать объекты по своему усмотрению, используя специальные контейнеры, такие как как Grid, Canvas и StackPanel.

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private bool _isDown;
    private bool _isDragging;
    private Point _startPoint;
    private UIElement _realDragSource;
    private UIElement _dummyDragSource = new UIElement();

    private void sp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (e.Source != this.sp)
        {
            _isDown = true;
            _startPoint = e.GetPosition(this.sp);
        }
    }

    private void sp_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _isDown = false;
        _isDragging = false;
        _realDragSource.ReleaseMouseCapture();
    }

    private void sp_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (_isDown)
        {
            if ((! _isDragging) && ((Math.Abs(e.GetPosition(this.sp).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
                (Math.Abs(e.GetPosition(this.sp).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
            {
                _isDragging = true;
                _realDragSource = e.Source as UIElement;
                _realDragSource.CaptureMouse();
                DragDrop.DoDragDrop(_dummyDragSource, new DataObject("UIElement", e.Source, true), DragDropEffects.Move);
            }
        }
    }

    private void sp_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("UIElement"))
            e.Effects = DragDropEffects.Move;
    }

    private void sp_Drop(object sender, DragEventArgs e)
    {

        if (e.Data.GetDataPresent("UIElement"))
        {
            UIElement droptarget = e.Source as UIElement;
            int droptargetIndex = -1, i = 0;
            foreach (UIElement element in this.sp.Children)
            {
                if (element.Equals(droptarget))
                {
                    droptargetIndex = i;
                    break;
                }
                i++;
            }
            if (droptargetIndex != -1)
            {
                this.sp.Children.Remove(_realDragSource);
                this.sp.Children.Insert(droptargetIndex, _realDragSource);
            }

            _isDown = false;
            _isDragging = false;
            _realDragSource.ReleaseMouseCapture();
        }
    }
}

MainWindow.xaml

<Window x:Class="DragShapes.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Border Background="Red">
    <StackPanel Name="sp" AllowDrop="True" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"
                PreviewMouseLeftButtonDown="sp_PreviewMouseLeftButtonDown" 
                PreviewMouseLeftButtonUp="sp_PreviewMouseLeftButtonUp" 
                PreviewMouseMove="sp_PreviewMouseMove"
                DragEnter="sp_DragEnter" Drop="sp_Drop">
        <Rectangle Height="80" Width="100" Fill="SkyBlue"  />
        <Rectangle Height="110" Width="90" Fill="LightGreen"  />
        <Rectangle Height="60" Width="60" Fill="Violet"  />
    </StackPanel>
    </Border>
</Window>
Другие вопросы по тегам