0
votes

I have a usercontrol that draws a selection rectangle which have a Selection Property that holds the value of the selection rectangle. Selection is bound two way in my main window so ViewModel have access to selectionRectangle values. Now I would like to change the size of the selectionRectangle by changing the Selection value inside my ViewModel. I'm trying to implement a PropertyChangedCallback in order to do this but I'm not knowledgeable enough to do so. What I currently have is an OnSelectionChanged method which if my PropertyChangedCallback is triggered would set the new value for my selectionRectangle. Below is the snippet of my code

In UserControl Dependency Property and OnSelectionChanged method:

      public static readonly DependencyProperty SelectionProperty =
        DependencyProperty.Register("Selection", typeof(Rect), typeof(CropControl), new PropertyMetadata(default(Rect))); 

    public Rect Selection
    {
        get 
        { 
            return (Rect)GetValue(SelectionProperty); 
        }
        set 
        {
            //if(this.Selection!=value)
                SetValue(SelectionProperty, value);
        }
    }

    // this is used, to react on changes from ViewModel. If you assign a  
    // new Rect in your ViewModel you will have to redraw your Rect here
    private static void OnSelectionChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        Rect newRect = (Rect)e.NewValue;
        Rectangle selectionRectangle = d as Rectangle;

        if (selectionRectangle != null)
            return;

        selectionRectangle.SetValue(Canvas.LeftProperty, newRect.X);
        selectionRectangle.SetValue(Canvas.TopProperty, newRect.Y);
        selectionRectangle.Width = newRect.Width;
        selectionRectangle.Height = newRect.Height;
    }

In my mainviewmodel there is nothing special just Selection property which gets and sets the value of the rectangle.

MainViewModel Selection property:

     private Rect selection;     //defines a Rect variable

    //getset accessor which is bound to views UserControl that gets the dimension of the rectangle from CropControl
    //and sets this dimension to private variable selection. The dimension will then be used to display the area 
    //cropped by the user.
    public Rect Selection
    {
        get
        {
            return selection;
        }
        set
        {
            selection = value;

            //// Or whatever the name of your framework/implementation the method is called
           SetPropertyChanged("Selection");

            //// Cause ICommands to reevaluate their CanExecute methods
            CommandManager.InvalidateRequerySuggested();
        }
    }

Now in DependencyProperty.Register i tried rewriting it and adding FrameworkPropertyMetadata since the change happens within another class but I'm not sure what object default value to use or if I'm doing this right.

    public static readonly DependencyProperty SelectionProperty =
        DependencyProperty.Register("Selection", typeof(Rect), typeof(CropControl), new PropertyMetadata(default(Rect)), new FrameworkPropertyMetadata(null,new PropertyChangedCallback(OnSelectionChanged));

THis give an Overloaded method match error.

1

1 Answers

0
votes

You do not need to create or register a dependency property to accomplish what you're trying to do. All you should have to do is raise the PropertyChanged event of the INotifyPropertyChanged interface from your main view model. Here is some example code for how I typically handle this.

public class MainViewModel : INotifyPropertyChanged
{
  // This event is for the INotifyPropertyChanged interace
  public event PropertyChangedEventHandler PropertyChanged;

  // This is a helper method that makes it straightforward to raise the PropertyChanged event
  public void NotifyPropertyChanged(string propertyName)
  {
    PropertyChangedEventHandler handler = this.PropertyChanged;

    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
  } 

  private Rect selection;
  public Rect Selection
  {
    get
    {
      return this.selection;
    }
    set
    {
      this.selection = value;

      // Alert the View that the property has been changed
      this.NotifyPropertyChanged("Selection");
    }
  }
}

Anytime you set the value of Selection from within the view model, any UI elements that bind to that property will automatically get updated.