I am new to DevForce and having trouble getting derived fields to work. In the WCF RIA world I'd simply use partial classes and virtual overrides to calculate things such as Tax and Totals. With DevForce I have the luxury of Interceptors, but I'm confused about how to raise a change notification in this scenario. I'm using MVVM, so lets start with the ViewModel:
Snippet public class MainViewModel : VM
{
private Order currentOrder;
public Order CurrentOrder
{
get { return currentOrder; }
set
{
if (currentOrder == value)
return;
currentOrder = value;
RaisePropertyChanged("CurrentOrder");
WriteToLog(CurrentOrder == null ? "No Order" : "Found order number " + CurrentOrder.OrderID);
}
}
private readonly NorthwindIBEntities mgr;
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
mgr = new NorthwindIBEntities();
mgr.Fetching += (s, e) => WriteToLog(e.Query);
mgr.Fetching += (s, e) => IsBusy = true;
mgr.Queried += (s, e) => IsBusy = false;
var q1 = from o in mgr.Orders
select o;
q1.ExecuteAsync(op => {
CurrentOrder = op.Results.First();
});
}
}
The CurrentOrder has a collection of OrderDetails, which is bound to a Grid like so:
Snippet <sdk:DataGrid AutoGenerateColumns="False" Height="200" ItemsSource="{Binding CurrentOrder.OrderDetails, Mode=TwoWay}">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Quantity" Binding="{Binding Quantity, Mode=TwoWay}" />
<sdk:DataGridTextColumn Header="Price" Binding="{Binding UnitPrice, Mode=TwoWay}" />
<sdk:DataGridTextColumn Header="Total" Binding="{Binding Total, Mode=OneWay}" />
</sdk:DataGrid.Columns>Finally, because I need to calculate the Total, I've extended the generated OrderDetail class as follows:
Snippetpublic partial class OrderDetail
{
private decimal total;
[Bindable(true, BindingDirection.TwoWay)]
[Editable(false)]
public Decimal Total
{
get { return total; }
private set
{
if (total == value)
return;
total = value;
NotifyPropertyChanged("Total");
}
}
[AfterSet(EntityPropertyNames.UnitPrice)]
[AfterSet(EntityPropertyNames.Quantity)]
[AfterSet(EntityPropertyNames.TaxID)]
[AfterSet(EntityPropertyNames.Discount)]
public void CalculateTotal(PropertyInterceptorArgs<OrderDetail, String> args)
{
Decimal discountPrice = UnitPrice - UnitPrice *(Decimal)Discount;
Decimal gst = Math.Round(discountPrice * Tax.Rate, 2);
Total = Quantity * (discountPrice + gst) ;
}
// Declare the PropertyChanged event
public event PropertyChangedEventHandler MyPropertyChanged;
// NotifyPropertyChanged will raise the PropertyChanged event passing the
// source property that is being updated.
public void NotifyPropertyChanged(string propertyName)
{
if (MyPropertyChanged != null)
{
MyPropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
There are several problems:
1. The total is not calculated. If I change the AfterSet to an AfterGet, then the Total IS calculated, but that seems very wrong to me.
2. Using an AfterGet, so that at least it triggers, if I set a breakpoint in the interceptor then I can see that the Total is calculated, but the value displayed is not updated.
I suspect that the problem is to do with change notification, but can't see what's wrong. Any help would be appreciated.
Dave.