Bind Canvas.Left and Canvas.Top in Style
attached-properties, binding, wpf
Solution
By default, binding will search for property in DataContext of control but `Location` is your control (Thing) property.
So you need to use `RelativeSource` with Mode set to `Self` to tell binding engine to search for property in control itself and not in DataContext of control:
<Setter Property="Canvas.Left" Value="{Binding Location.X,
RelativeSource={RelativeSource Self}}"/>
Problem
I am trying to reflect a position from my view-model expressing the location of an object in my view by binding the `Canvas.Left` and `Canvas.Top` properties in the style of the item view to appropriate properties in the view-model. However, the bindings do not seem to work. For this minimal sample, I have simplified the structure so there only is one control `Thing` that is styled and templated: ``` using System; using System.Windows; using System.Windows.Controls; namespace LocationBinding { public class Thing : Control { static Thing() { DefaultStyleKeyProperty.OverrideMetadata(typeof(Thing), new FrameworkPropertyMetadata(typeof(Thing))); } public Point Location { get { return new Point(70, 70); } } public double VPos { get { return 100; } } } } ``` For the sake of simplicity, I have declared the style in the resource dictionary of the main window - a simple window with a canvas on it (my real project has this in `Themes\Generic.xaml`). In its style, I am binding to property values of the control: ``` <Window x:Class="LocationBinding.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:LocationBinding" Title="LocationBinding" Height="300" Width="300"> <Window.Resources> <Style TargetType="local:Thing"> <Setter Property="Panel.ZIndex" Value="542"/> <Setter Property="Canvas.Left" Value="{Binding Location.X}"/> <Setter Property="Canvas.Top" Value="{Binding VPos}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:Thing"> <Ellipse Fill="ForestGreen" Width="30" Height="30"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Canvas Name="cnv"> </Canvas> </Window> ``` The code-behind of the main window simply adds a `Thing` instance to the canvas: ``` using System; using System.Windows; namespace LocationBinding { public partial class Window1 : Window { public Window1() { InitializeComponent(); cnv.Children.Add(new Thing()); } } } ``` The style is correctly applied, as evidenced by the `ZIndex` value (according to Snoop) and the correct template-based appearance of the control. However, `Canvas.Left` and `Canvas.Top` remain unset (and thus the `Thing` sticks in the top left corner of the canvas), even though according to threads such as this or this, `Property="Canvas.Left"` seems to be the correct syntax to refer to the attached property in a style. I was first trying to bind `Canvas.Top` to `Location.Y` and replaced that with the `VPos` property in case the problem is related to binding to struct properties, but that does not seem to change anything, either. What am I missing; how can I bind `Canvas.Left` and `Canvas.Top` in my style to the coordinates from my `Thing.Location` property?