Hidden paths of MVVM - Calc Field and Dynamic Value

I will save you the theatrics and plunge straight into the issue at hand. I am getting my feet wet with MVVM methodology using XAML and I had a situation where I needed to have a calc field assigned to computed dynamic value. My data layer consisted of a strongly typed dataset.

After googling a couple of times, i found out there is a property called EXPRESSION that you can actually use with calc fields to derive values but it has a finite set of notations that you can specify at design time. Specifically, design time specification is only good for STATIC or known finite set of values. A lot of articles out there suggest using the "Column Change" and/or "Column Changed" events to assign complex values to a calc field. For whatever reason, I could not get the calc field populated using either of these events. I actually suspect the reason why the handlers for the events were not firing was becuase of the fact that I was doing a "READ ONLY" ( search) operation. Most likely, if I had attempted to update/save any of the columns, one of them would have fired.

Anyway, long story short, I did more "googling" and found other hints of using "Row Change" or/and "Row Changed" events instead. It appeared initially to be what I was looking for but then I was having an unhandled exception being thrown. Apparently, changing a column value while executing a RowChanging event also triggers another RowChanging event call to be made thereby leading to a recursive situation and eventually loss of memory. Again, I did more googling and found a post that described exactly what needed to be done. Basically, to prevent the recursion when assigning a column value in the "Rowchanging" event hanlder - one needs to have a private boolean value that is set the first time and then, when a calc field value is assigned, it is toggled. Subsequent call to the RowChanging event then tests for the boolean value and if it is set, aborts processing of the RowChanging event and then toggles the boolean value back.

The following steps are required - 1. Overide the EndInit() method and specify your event handler for the RowChanged Event.

public override void EndInit(
{
base.EndInit();
// this is just a template to show how validation can be done with dataset
// if Calc Field Can be done with expression, use it , otherwise use RowChanged event

// This method call establishes EXPRESSION values at run time. This is ok if EXPRESSION value is STATIC
prcIntiDataColumExpression();

// Initialiaze the private variable used in tracking execution state of RowChnaged event handler
_Rowchanged = false;
// Not sure - looks like the event is added twice - so, try and unhook it first if it exist before adding
RowChanged -= new DataRowChangeEventHandler(Row_Changing);
RowChanged += new DataRowChangeEventHandler(Row_Changing);
}

2.Define a private variable to track the state of exeuction of the event handler.
private bool _Rowchanged = false;
3. In the event handler for the RowChanged Event, test for the state of the private variable and only excute getting the calc field value when it is false;
// This is the Row Changing event handler
private void Row_Changing(object sender, DataRowChangeEventArgs e)
{
// Row_Changing is fired recursively anytime the value is changed, to avoid cyclic stuff
// check if was called before
if (_Rowchanged )
{
// this is likely triggered because of the invocaktion of prcAddressCalcChange
_Rowchanged = false;
}
else
{
_Rowchanged = true;
//call actual method to set the value for the calc field
prcAddressCalcChange(e);
}
}

With this simple trick, you can actually assign dynamically computed values to your calc fields.

Comments

Popular posts from this blog

Decompiling Delphi - 3

Decompiling Delphi - 2

Artificial Intelligence, Oxymoron and Natural Intelligence