PGP-Protector

Coding

Binding and DependencyProperty

by 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.

Leave a Comment more...

C# WPF Registered names

by on Jul.18, 2011, under Coding

I was working on a project that was using Registered names on a WPF Form for paths so that the user can select them, over all it was working quite well, until the user was required to delete some on them (in random order)

After a small bit of tweaking, I also got that working.  Though it did bring up another issue.  When I wanted to Clear the canvas, their was no easy way to also clear all the left over Registered names on the existing paths, and not every path had a registered name.

My final solution was to come up with this small routine.  It at least appear to do the job.

 

 

        private void ClearRegisteredNames(Canvas CanvasToClear)
        {
            if (CanvasToClear != null)
            {
                foreach (object ChildObject in LogicalTreeHelper.GetChildren(CanvasToClear))
                {
                    Type Name = ChildObject.GetType();
                    if (Name == typeof(Path))
                    { 
                        // Get Path Name if Any?
                        Path FoundPath = (Path)ChildObject;
                        string PathName = FoundPath.Name;
                        if (PathName != "") CanvasToClear.UnregisterName(PathName);
                    }
                }
            }
        }
Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!