Binding and DependencyProperty
by PGP_Protector on Apr.11, 2013, under Coding
Long story short.
I was trying to create a custom object that I can bind to, not bind from.
So off to google dealing with WPF, Binding, UserControls, ect….
Lots of results on how to bind a variable to a text box, data table , list to drop boxes and all that, but What I was wanting to do was a bit different.
I wanted to use my own control that draws a “Target” on a canvas map, and allows you to Move the Target just by updating the Location(a System.Windows.Point) should be simple right?
Well it is after you figure out what you’re doing 🙂
My Thread that generates the X,Y coordinates for a Robot Map was running find, and the X & Y Values were bound to a text box on the main form, so I know it’s running fine in the background.
Any time it changes the X Or Y Value, it would also update the Location Point, and send a NotifyPropertyChanged(“CurrentLocation”); to boot. That was working fine also.
But how to get my control to receive it?????
There were two problems.
1) it wasn’t a single variable I’m trying to get, but a Point object
2) how to allow it to Receive the Binding, not Set a binding.
So I give you the solution that I found, (And it works for me) though I’m sure it needs improvements.
using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; namespace MyApplication { public class TargetCurser : UserControl { public static readonly DependencyProperty TargetProperty = DependencyProperty.Register("MyPoint", typeof(Point), typeof(TargetCurser),new PropertyMetadata(new Point(0,0),OnTargetPropertyChanged)); private Point _MyPoint = new Point(0, 0); public Point MyPoint { get { return _MyPoint; } set { _MyPoint = value; MoveTo(MyPoint); } } private static void OnTargetPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { TargetCurser control = sender as TargetCurser; if (control != null) { control.MyPoint = (Point)e.NewValue;} } private Path TargetObject = null; private Canvas TargetsCanvas = null; private Path TObject(string ObjectName, double Size, Color TargetColor) { // Snip COde, just build a Path of what you want and store it in LinePath to return. return LinePath; } private void MoveTo(Point NewLocation) { if (TargetsCanvas == null) return; // Can't move if we're not given a valid surface to move on. if (TargetObject == null) return; // Can't Move if we haven't build the TargetObject Path FindTargetOnCanvas = TargetsCanvas.FindName(TargetObject.Name) as Path; if (FindTargetOnCanvas == null) return; // Unable to Find Target on Path, can't move it. FindTargetOnCanvas.SetValue(Canvas.TopProperty, NewLocation.Y * ScalingFactor); FindTargetOnCanvas.SetValue(Canvas.LeftProperty, NewLocation.X * ScalingFactor); } public TargetCurser(Canvas DrawOn, string TargetsName) { UIElement ExistCheck = DrawOn.FindName(TargetsName) as UIElement; if (ExistCheck != null) { DrawOn.UnregisterName(TargetsName); DrawOn.Children.Remove(ExistCheck); } TargetObject = TObject(TargetsName, 5, Colors.Red); TargetsCanvas = DrawOn; TargetsCanvas.RegisterName(TargetObject.Name, TargetObject); TargetsCanvas.Children.Add(TargetObject); MoveTo(MyPoint); } } }
Now for a bit of explaining.
1) You don’t need the INotifyPropertyChanged bit of code for a control that will be RECEIVING the Binding unless you’re also changing values and wish to send it back out.
2) public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(“MyPoint”, typeof(Point), typeof(TargetCurser),new PropertyMetadata(new Point(0,0),OnTargetPropertyChanged));
This is where I was having the trouble, It would “Bind” tell I modified the last part PropertyMetadata(Default Value, WhatToDo)
Given my object is expecting a Point, I used new Point(0,0) vs a Null or 0 or “” like in some of the examples I saw on the net.
and the WhatToDo / OnTargetPropertyChanged (What ever void Property you’re wanting called when the variable bound to this changes);
3) private static void WhatToDo(DependencyObject sender, DependencyPropertyChangedEventArgs e)
This is where you’ll process any data that is Sent to your object / class when the Data Bound to your class changes, the new & old value will be in “e” (PropertyChangedEventArgs.