Domanda

Sto creando controlli (pulsante diciamo) su una griglia. Voglio creare una linea di collegamento tra i controlli. Diciamo che si fa mousedown su un pulsante del mouse e il rilascio su un altro pulsante. Questo dovrebbe tracciare una linea tra questi due pulsanti.

Qualcuno può aiutarmi o darmi qualche idea su come fare questo?

Grazie in anticipo!

È stato utile?

Soluzione

sto facendo qualcosa di simile; ecco un breve riassunto di quello che ho fatto:

Drag & Drop

Per la gestione del drag-and-drop tra i controlli c'è un po 'di letteratura sul web ( basta cercare WPF drag-and-drop ). L'implementazione di drag-and-drop di default è eccessivamente complesso, IMO, e abbiamo finito per l'utilizzo di alcuni PS attaccato per rendere più facile ( simili a questi ). In sostanza, si vuole un metodo di trascinamento che sembra qualcosa di simile:

        private void onMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            UIElement element = sender as UIElement;
            if (element == null)
                return;
            DragDrop.DoDragDrop(element, new DataObject(this), DragDropEffects.Move);
        }

Sulla destinazione, impostare AllowDrop su true, quindi aggiungere un evento a goccia:

    private void onDrop(object sender, DragEventArgs args)
    {
        FrameworkElement elem = sender as FrameworkElement;
        if (null == elem)
            return;
        IDataObject data = args.Data;
        if (!data.GetDataPresent(typeof(GraphNode))
            return;
        GraphNode node = data.GetData(typeof(GraphNode)) as GraphNode;
        if(null == node)
            return;

        // ----- Actually do your stuff here -----
    }

Drawing the Line

Ora per la parte difficile! Ogni controllo espone un AnchorPoint DependencyProperty . Quando l'evento viene generato LayoutUpdated (cioè quando i movimenti di controllo / ridimensiona / etc), il controllo ricalcola sua AnchorPoint. Quando si aggiunge una linea di collegamento, si lega alle DependencyProperties sia la fonte e AnchorPoints di destinazione. [ Modifica : Come Ray Burns ha sottolineato nei commenti sulla tela e la griglia solo bisogno di essere nello stesso luogo; non hanno bisogno di essere int stessa gerarchia (per quanto possano essere)]

Per aggiornare la posizione DP:

    private void onLayoutUpdated(object sender, EventArgs e)
    {
        Size size = RenderSize;
        Point ofs = new Point(size.Width / 2, isInput ? 0 : size.Height);
        AnchorPoint = TransformToVisual(node.canvas).Transform(ofs);
    }

Per creare la classe di linea (può essere fatto in XAML, anche):

public sealed class GraphEdge : UserControl
{
    public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(Point), typeof(GraphEdge), new FrameworkPropertyMetadata(default(Point)));
    public Point Source { get { return (Point) this.GetValue(SourceProperty); } set { this.SetValue(SourceProperty, value); } }

    public static readonly DependencyProperty DestinationProperty = DependencyProperty.Register("Destination", typeof(Point), typeof(GraphEdge), new FrameworkPropertyMetadata(default(Point)));
    public Point Destination { get { return (Point) this.GetValue(DestinationProperty); } set { this.SetValue(DestinationProperty, value); } }

    public GraphEdge()
    {
        LineSegment segment = new LineSegment(default(Point), true);
        PathFigure figure = new PathFigure(default(Point), new[] { segment }, false);
        PathGeometry geometry = new PathGeometry(new[] { figure });
        BindingBase sourceBinding = new Binding {Source = this, Path = new PropertyPath(SourceProperty)};
        BindingBase destinationBinding = new Binding { Source = this, Path = new PropertyPath(DestinationProperty) };
        BindingOperations.SetBinding(figure, PathFigure.StartPointProperty, sourceBinding);
        BindingOperations.SetBinding(segment, LineSegment.PointProperty, destinationBinding);
        Content = new Path 
        {
            Data = geometry,
            StrokeThickness = 5,
            Stroke = Brushes.White,
            MinWidth = 1,
            MinHeight = 1
        };
    }
}

Se si desidera ottenere un amatore molto, è possibile utilizzare un MultiValueBinding su origine e di destinazione e aggiungere un convertitore che crea il PathGeometry. Ecco un esempio da GraphSharp. Utilizzando questo metodo, è possibile aggiungere le frecce per alla fine della linea, utilizzare le curve di Bézier per farlo sembrare più naturale, percorso la linea intorno altri controlli ( se questo potrebbe essere più difficile di quanto sembri ), ecc, ecc.


Vedi anche

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top