Hi,
I have noticed a "bug" or something when using navigation properties with data-binding. Let me take a practical example. It is pretty long, but very simple.
I have an entity EntOpcGroup with an navigtion property EntDevice.
In a dataform (actually an AtomForm http://akashkava.com/blog/) I present EntOpcGroup but also EntDevice.p_name. So I was going to do a lazy load of EntDeivce only when the user requested each EntOpcGroup. First I did this such, and it worked 100%:
XAML databinding:
<ns:AtomForm x:Name="c_DeviceForm"
DataContext="{Binding p_currentItem, Mode=TwoWay}"
....
<ns:AtomTextBox x:Name="c_deviceType"
Text="{Binding p_vm.p_deviceName, Source={StaticResource ViewModelLocator}, Mode=OneWay}"
....
View Model code:
#region Device lazy loading and bound property for Device Type Name
/// <summary>
/// Performs lazy loading of Device when an EntOpcGroup is selected
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "p_currentItem")
{
var entOpcGroup = (EntOpcGroup)p_currentItem;
if (entOpcGroup.p_device.EntityAspect.IsPendingEntity)
// The device has not been loaded from database. Ask for lazy loading and set event handler
entOpcGroup.p_device.EntityAspect.PendingEntityResolved += OnPendingEntDeviceResolved;
else
// The device is already loaded, notify the bound XAML text box.
RaisePropertyChanged("p_deviceName");
}
}
/// <summary>
/// The devuce is received from the database with the lazy load triggerd in OnPropertyChanged.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPendingEntDeviceResolved(object sender, PendingEntityResolvedEventArgs e)
{
RaisePropertyChanged("p_deviceName");
((Entity)sender).EntityAspect.PendingEntityResolved -= OnPendingEntDeviceResolved;
}
public string p_deviceName
{
get
{
if (p_currentItem == null)
return null;
return ((EntOpcGroup)p_currentItem).p_device.p_name;
}
}
#endregion
Then I wanted to eliminate the p_deviceName property that is actualy outside the p_currentItem that is bound to the form. So I did those changes:
XAML:
<ns:AtomForm x:Name="c_DeviceForm"
DataContext="{Binding p_currentItem, Mode=TwoWay}"
....
<ns:AtomTextBox x:Name="c_deviceType"
Text="{Binding p_deviceName, Mode=OneWay}"
....
View Model code:
#region Device lazy loading and bound property for Device Type Name
/// <summary>
/// Performs lazy loading of Device when an EntOpcGroup is selected
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "p_currentItem")
{
var entOpcGroup = (EntOpcGroup)p_currentItem;
if (entOpcGroup.p_device.EntityAspect.IsPendingEntity)
// The device has not been loaded from database. Ask for lazy loading and set event handler
entOpcGroup.p_device.EntityAspect.PendingEntityResolved += OnPendingEntDeviceResolved;
}
}
/// <summary>
/// The device is received from the database with the lazy load triggerd in OnPropertyChanged.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPendingEntDeviceResolved(object sender, PendingEntityResolvedEventArgs e)
{
RaisePropertyChanged("p_deviceName");
((Entity)sender).EntityAspect.PendingEntityResolved -= OnPendingEntDeviceResolved;
}
And then I define p_deviceName in EntOpcGroup such:
public partial class EntOpcGroup
{
/// <summary>
/// Added for binding convenience
/// </summary>
public string p_deviceName2 {get{return p_device.p_name;}}
}
Now when I run this code it does not work properly (but almost). The strange thing is that when OnPendingEntDeviceResolved is triggered, IsPendingEntity=false as expected but there is no data in the EntDevice instance (the “sender” parameter) an it is still Detatched. However if I select another instance of EntOpcGroup and back to the first again then the EntDevice.p_name is displayed correctly in the form. When I investigate that time in the debugger the EntDevice instance has data and is no more Detatched.
So it seems like the OnPendingEntDeviceResolved happens “a little bit too eraly”.
The only code difference is actually the binding. That is to say in the first case I bind to an “external” property in the view model. But in the later case I bind directly to a added property in EntOpcGroup.
This is probably a bug or what?!?!