Caliburn Micro Guard Methods not evaluating on property change
Asked Answered
C

3

18

I've been playing with the Caliburn Micro MVVM framework and am having some problems with guard methods.

I have a view model:

public class MyViewModel : PropertyChangedBase, IMyViewModel

A property:

public DateTime? Date
{
   get{return this.date; }
   set
   {
      this.date = value;
      this.NotifyOfPropertyChange(() => Date);
   }
}

Also, i have a method in my view model with a guard method

public void Calculate()
{
    // ..some code..
}

public bool CanCalculate()
{
    return this.Date.HasValue;
}

And a button in my view:

The problem I am having is that the CanCalculate method executes when loading but when I enter values into the text fields, it doesn't reevaluate the CanCalculate method. I am firing the property changed event on setting the databound view model properties so what could be the problem?

Chanterelle answered 5/4, 2011 at 2:33 Comment(1)
Could you show the code for the view, and also where you invoke the NotifyOfPropertyChanged method in your view model?Heliacal
C
34

Ok I figured it out. I didn't realise that you have to fire the guard method notification, thought the framework did that, but it makes sense.

So I change my property setter to:

public DateTime? Date
{
   get
   {
      return this.date; 
   }
   set
   {
      this.date = value;
      this.NotifyOfPropertyChange(() => Date);
      this.NotifyOfPropertyChange(() => CanCalculate);
   }
}

and changed my CanCalculate method to a property:

public bool CanCalculate
{
    get
    {
        return this.Date.HasValue;
    }
}

And all works fine now :)

Chanterelle answered 5/4, 2011 at 17:1 Comment(2)
Just turn it onto a boolean Property with a getter.Gleda
For anyone coming across this trying to make it work for guard methods with parameters: If the parameter object is contained in another property (for example, a collection is bound to a listbox and the guard is per-item) you can just notify property changed for the (seemingly) irrelevant property.Walkerwalkietalkie
R
2

If you dont need CanExecute to be method, because you wont use parameters. Then you can rewrite it as property with standard notification and only getter. And call its PropertyChanged when you asume result of the getter changed.

Rachealrachel answered 5/4, 2011 at 5:16 Comment(0)
F
0

I am assuming these are called via a Command (some code around what is call those methods would help).

If the case you are having is that you want the commands to revevaluate based on some input you need to invoke CommandManager.InvalidateRequerySuggested() so the commands CanExecutes will get called. Since the command is bound to the button and not the textbox it will not update. In your property setter (the one bound to the textbox) you have to tell the framework to requery the commands. This in turn will call your CanCalculate method.

If the Calculate and CanCalculate methods are not associated with a command then the above will not help.

Fulgurite answered 5/4, 2011 at 2:39 Comment(2)
Caliburn Micro seems to ignore CommandManager.InvalidateRequerySuggested(), bit of an oversight actually. :/Plato
It's not an oversight. Caliburn.Micro doesn't use Commands at all - it has Actions/ActionMessages.Ryder

© 2022 - 2024 — McMap. All rights reserved.