Where we are:

  • We have introduced the design time data concepts;
  • We have understood how to setup a design time experience using Radical;
  • We have discovered how to let the designers lively change values at design time;

We want more!

Start changing the view model we are designing adding a couple of properties:

class PersonViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = ( s, e ) => { };

    private void OnPropertyChanged( string propertyName )
    {
        var h = this.PropertyChanged;
        h( this, new PropertyChangedEventArgs( propertyName ) );
    }

    String _firstName;

    public String FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            this.OnPropertyChanged( "FirstName" );
        }
    }

    String _lastName;

    public String LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            this.OnPropertyChanged( "LastName" );
        }
    }

    DateTime _bornDate;

    public DateTime BornDate
    {
        get { return _bornDate; }
        set
        {
            _bornDate = value;
            this.OnPropertyChanged( "BornDate" );
            this.OnPropertyChanged( "Age" );
        }
    }

    public Int32 Age
    {
        //stupid and wrong but it's a sample :-)
        get { return DateTime.Now.Year - this.BornDate.Year; }
    }
}

We want to reflect that behavior in our design time view model, let’s start exposing a live property for the BornDate property:

public DesignTimePersonViewModel()
{
    this.Expose( vm => vm.FirstName )
        .WithLiveValue( () => this.DesignTime_FirstName );

    this.Expose( vm => vm.LastName )
        .WithLiveValue( () => this.DesignTime_LastName );

    this.Expose( vm => vm.BornDate )
        .WithLiveValue( () => this.DesignTime_BornDate );
}

public DateTime DesignTime_BornDate
{
    get { return this.GetPropertyValue( () => this.DesignTime_BornDate ); }
    set { this.SetPropertyValue( () => this.DesignTime_BornDate, value ); }
}

Now we now, as we have seen last time, that we can edit the BornDate property directly in the designer,  but what about the Age property? it is a runtime evaluated property.

Enter design time evaluated properties, aka dynamic properties:

public DesignTimePersonViewModel()
{
    this.GetPropertyMetadata( () => this.DesignTime_BornDate )
        .AddCascadeChangeNotifications( "Age" );

    this.Expose( vm => vm.FirstName )
        .WithLiveValue( () => this.DesignTime_FirstName );

    this.Expose( vm => vm.LastName )
        .WithLiveValue( () => this.DesignTime_LastName );

    this.Expose( vm => vm.BornDate )
        .WithLiveValue( () => this.DesignTime_BornDate );

    this.Expose( vm => vm.Age )
        .AsReadOnly()
        .WithDynamicValue( ci => ( int )( ( DateTime.Now - this.DesignTime_BornDate ).TotalDays / 365 ) );
}

We are doing some important things:

  1. we are telling to the infrastructure that whenever the DesignTime_BornDate property changes we want a changed event even for the Age property, I’m thinking about a better API to express this;
  2. We are building a dynamic value based property where the value is a Func<CultureInfo, TValue> that is invoked by the infrastructure to read the property value;
  3. Least but not last we are telling to the designer that the exposed Age property is a read-only property as in the original ViewModel;

And obviously the designer behaves as expected, immediately reflecting our inputs:

image

And the generated xaml code is exactly what we expect.

In the next episode of this series we’ll dive into a much more complex ViewModel scenario.

Stay tuned!

.m