Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding to Canvas.Left breaks when element is moving

I have the following Canvas which has 3 elements:

            <Rectangle x:Name="start" Canvas.Left="20" Canvas.Top="100" Width="25" Height="25" Fill="Pink"/>


            <Line X1="{Binding ConverterParameter=X, ElementName=start, Converter={StaticResource CanvasPositionConverter}}" 
                  Y1="{Binding ConverterParameter=Y, ElementName=start, Converter={StaticResource CanvasPositionConverter}}" 
                  X2="{Binding ConverterParameter=X, ElementName=root, Converter={StaticResource CanvasPositionConverter}}" 
                  Y2="{Binding ConverterParameter=Y, ElementName=root, Converter={StaticResource CanvasPositionConverter}}"  
                  Stroke="Red" StrokeThickness="2" />

          <!--I have something external that controls the position of this dockpanel on the canvas so on runtime it may move-->
            <DockPanel x:Name="root" Canvas.Left="0" Canvas.Top="0" Width="20" Height="20" />

where CanvasPositionConverter is this:

   public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {

        if (parameter.ToString().ToLower() == "x")

            return Canvas.GetLeft(value as FrameworkElement);

        else if (parameter.ToString().ToLower() == "y")

            return Canvas.GetTop(value as FrameworkElement);


        else throw new Exception("Need a ConverterParameter of either X or Y");
    }

It does work on startup, meaning the initial values of the bindings are correct (as shown in Snoop); the problem is the dockpanel is moving at runtime but the bindings do not update to the new location of the dockpanel. Basically I want a line that connects a static shape to a moving shape. (The moving shape is actually in an adorner which the user can drag to move)

like image 367
baye dbest Avatar asked Feb 15 '23 09:02

baye dbest


1 Answers

Your bindings are not updated because you don't bind to any property of the root or start elements, but instead retrieve the property values directly from the source object by a binding converter.

Fortunately you don't need that converter. Just write the bindings like this:

<Line X1="{Binding Path=(Canvas.Left), ElementName=start}" 
      Y1="{Binding Path=(Canvas.Top), ElementName=start}" 
      X2="{Binding Path=(Canvas.Left), ElementName=root}" 
      Y2="{Binding Path=(Canvas.Top), ElementName=root}"  
      Stroke="Red" StrokeThickness="2" />

Note that the name of an attached property should be put in parentheses in a binding property path.

like image 180
Clemens Avatar answered Feb 19 '23 19:02

Clemens