codeputer
codeputer

Reputation: 2018

Silverlight / DataBinding / EntityRef

I been having a DataBinding program that I would think be a fairly common occurrance, but I can't seem to find anybody with a similar problem - which leads me to think that I'm missing something..

In short, after saving a new Parent entity, the Parent Entity cannot seem to refer to an EntityRef during binding operations and refer to attributes on a related Entity…. here comes the detail…

I have a hierarchical structure that looks like this: Organization has one or more Representatives, where each Representative is a Person, each Person that has zero or more Telephone Numbers.

So Organization->>Representative->Person->>TelephoneNumbers.

I’m using a list box to show a list of Representatives on the left, and the right side displays the detail information for the Representative that is selected. I used the selected item in the ListBox as the source for a grid that displays Person information.

I’m using WCF RIA Services, so I have an Entity object called Organization, which contains an EntitySet collection of Representatives, which I use as the itemsource to bind to the list box.

Within each Representative there is a Person object, which leads me to the Person First name and Last Name (internally this is where the EntityRef comes to play).

In the Representative box, I would like to show the Representative Title, as well as their related First and Last Name (which is on the related entity Person). So the list box would contain something like this:

Title First Name Last Name District Manager Bill Smith Area Manager John Doe

XAML looks like this:

 <ListBox> 
   <ListBox.ItemTemplate>
    <DataTemplate>
        <Grid>

           <Grid.ColumnDefinitions>

             <ColumnDefinition/>

             <ColumnDefinition/>

             <ColumnDefinition/>

           </Grid.ColumnDefinitions>

           <TextBlock Grid.Column="0" Text="{Binding ContactTitle}" Margin="5"/>

          <TextBlock Grid.Column="1" Text="{Binding Path=Person.FirstName, Mode=OneWay,    FallbackValue='New Representative'}" Margin="5"/>

          <TextBlock Grid.Column="2" Text="{Binding Path=Person.LastName, Mode=OneWay, FallbackValue='New Representative'}" Margin="5"/>

        </Grid>

     </DataTemplate>

  </ListBox.ItemTemplate>

</ListBox>

When I create a new Representative, I also create a new Person record, and immediate associate the new Person with the Representative, and the Representative with an Organization.

Everything works great until I save the DomainContext. When I submit the changes back via RIA Services, I’ve traced it all through the Submit, and it updates the DB works perfectly. The Submitted Results, which are returned after the submit operation is completed, looks good as well.

I’ve confirmed that the Org, Rep, and Person are all related correctly in the client side application.

YET, when I return to the Listbox, both the first and last name of the Person ARE LOST! I’ve spent hours and hours (days in fact) trying to determine why, but can’t seem to find a way to trace what happens between the Submitcallback, and the return to the screen.

In my debugging, I added a SelectionChanged event handler, and added a break point. When I click on the new saved row, and look at the Person – it’s not null, and it contains the correct data - yet the list box is displaying the FallBack attribute.

Why does Databinding receive a null after the Submit operation completes, yet it is there when I hit my breakpoint on selectionchanged. I’m sure it’s a timing issue – but surely this requirement has been met before!

Upvotes: 2

Views: 392

Answers (3)

codeputer
codeputer

Reputation: 2018

I think I understand why this is a problem, but I still don't understand why it's not more of a problem to a lot of people.

I use surrogate keys, and this problem only occurs after a submit. I have gone pretty deep to see if the client side DomainService model is holding this data correctly after an add, and I'm now convinced it is.

However, I think this is a timing issue. The parent has to be added first into the model, before the children. Yet the grid is bound to the parent, with reference to navigation properties to display children data. In this case the cardinalty is one-to-one, but the load of one has to happen until the load of the second one.

My thought here is that one entity is loaded, and hence properties raises. The control responds to the raise property, and gets the data. This happens however before the "child" entity is loaded, and the EntityRef navigation property returns a null. The child entities are then loaded directly after, but because the binding has already occurred on the parent, the control does not "see" the data.

I found that if I rebind the control, (Silverlight), everything shows up. However, in MVVM, this is a tight coupling between the VM finishing a load, and the control having to do a rebind. I've tried re-raising the property changed events, but the control does not respond.

I will have to take the time to create a small project with the error, and pass it on to tech support for clarification.

Upvotes: 0

Ehsan Zargar Ershadi
Ehsan Zargar Ershadi

Reputation: 24833

This is a little bit tricky. To debug the binding i use a fake convertor and placing a break point at the commented line shown bellow:

public class DummyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value; // <- place you break point here
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

and you need to use it in your xaml :

<Grid>
    <Grid.Resources>
        <local:DummyConverter x:Key="DummyConv"/>
    </Grid.Resources>

    <TextBlock Text="{Binding MyText,Converter={StaticResource DummyConv}}"/>
</Grid>

and now you can see how the value in the Converter changes and if it does not reaches the break pint it means you have lost your binding (or you have no such property in your DataContext)

Upvotes: 1

Ehsan Zargar Ershadi
Ehsan Zargar Ershadi

Reputation: 24833

IMO you are losing your bindig, I'm not sure but this situation happens when you set its data manually while it has been binded.

Upvotes: 1

Related Questions