Search code examples
c#.netwpfpixelsense

Connect 2 ScatterViewItems with a line?


I use the following code to connect two ScatterViewItems. Unfortunately this does not work because the center property isn't asingle value. But I can't read out values x and y from the CenterProperty:

Line l = new Line();
                    l.Stroke = Brushes.Green;
                    l.StrokeThickness = 10;
                    Binding x1 = new Binding(); x1.Path = new PropertyPath(ScatterViewItem.CenterProperty);
                    x1.Converter = new MyConverter();
                    x1.ConverterParameter = root;
                    Binding y1 = new Binding(); y1.Path = new PropertyPath(ScatterViewItem.CenterProperty);
                    y1.Converter = new MyConverter();
                    y1.ConverterParameter = root;
                    Binding x2 = new Binding(); x2.Path = new PropertyPath(ScatterViewItem.CenterProperty);
                    x2.Converter = new MyConverter();
                    x2.ConverterParameter = level1;
                    Binding y2 = new Binding(); y2.Path = new PropertyPath(ScatterViewItem.CenterProperty);
                    y2.Converter = new MyConverter();
                    y2.ConverterParameter = level1;
                    x1.Source = y1.Source = root;
                    x2.Source = y2.Source = level1;
                    l.SetBinding(Line.X1Property, x1);
                    l.SetBinding(Line.Y1Property, y1);
                    l.SetBinding(Line.X2Property, x2);
                    l.SetBinding(Line.Y2Property, y2);
                    Dependencies.Children.Add(l);
                    l.Tag = new Call(focus, file);

                    Contacts.AddPreviewContactDownHandler(l, OnLineDown);

                    SizeChangedEventHandler act = (Object s, SizeChangedEventArgs args) =>
                    {
                        BindingOperations.GetBindingExpressionBase(l, Line.X1Property).UpdateTarget();
                        BindingOperations.GetBindingExpressionBase(l, Line.Y1Property).UpdateTarget();
                        BindingOperations.GetBindingExpressionBase(l, Line.X2Property).UpdateTarget();
                        BindingOperations.GetBindingExpressionBase(l, Line.Y2Property).UpdateTarget();
                    };

                    root.SizeChanged += act;
                    level1.SizeChanged += act;

Solution

  • I'm now using the followng solution, proposed in the Microsoft Surface Development forum by Sebastian:

    XAML:

    <s:SurfaceWindow
        x:Class="Lines.SurfaceWindow1"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:s="http://schemas.microsoft.com/surface/2008"
        Title="Lines"
        >
    
        <Grid>
            <Canvas x:Name="LineHost"/>
            <s:ScatterView x:Name="ScatterView"/>
        </Grid>
    
    </s:SurfaceWindow>
    

    Code-behind:

    private void BindLineToScatterViewItems(Line line, ScatterViewItem origin,
        ScatterViewItem destination)
    {
        // Bind line.(X1,Y1) to origin.ActualCenter  
        BindingOperations.SetBinding(line, Line.X1Property, new Binding {
            Source = origin, Path = new PropertyPath("ActualCenter.X") });  
        BindingOperations.SetBinding(line, Line.Y1Property, new Binding {
            Source = origin, Path = new PropertyPath("ActualCenter.Y") });
    
        // Bind line.(X2,Y2) to destination.ActualCenter  
        BindingOperations.SetBinding(line, Line.X2Property, new Binding {
            Source = destination, Path = new PropertyPath("ActualCenter.X") });  
        BindingOperations.SetBinding(line, Line.Y2Property, new Binding {
            Source = destination, Path = new PropertyPath("ActualCenter.Y") });
    }
    

    Then if you want to create a line between two ScatterViewItems, simply do this:

    var origin = new ScatterViewItem();
    var destination = new ScatterViewItem();
    Line line = new Line { Stroke = Brushes.Black, StrokeThickness = 2.0 };
    BindLineToScatterViewItems(line, origin, destination);
    
    ScatterView.Items.Add(origin);
    ScatterView.Items.Add(destination);
    LineHost.Children.Add(line);