views:

210

answers:

1

I recently wrote an implementation of a VirtualizingWrapPanel that recycles containers as they scroll into and out of view.

On occasion I've noticed that the content rendered by the control is actually the previously contained data, not the current data. Performing any action on the control that forces a new render call updates the control such that it displays the correct data.

Could this a bug in the ItemContainerGenerator recycling or is it more likely in my recycling code? Is there a way I can force all my bindings to update (after updating the control with new content) without explicitly writing each binding expression in code behind?

A: 

I've seen problems very like this in the past when using virtualization when we were using custom controls that really weren't expecting their DataContexts to be changed once they were displayed.

If your panel is correctly (as it sounds) handing new DataContexts to the reused objects then it does sound like the reused objects aren't processing that DataContext change correctly. (This 'render' call you talk about would then pick up the new DataContext and display that.)

If you're using plain data binding in your control then I'm slightly stumped. (Is your panel re-Measure/Arranging the controls after they've got their new DataContext?)

The fix for us was to have our controls listen out for when their DataContext changed. (This is also useful for debugging virtualizing panels to test that the DataContext is coming in correctly.)

Sadly the OnDataContextChanged method isn't public in Silverlight but you can still find out about DC changes by binding to them.

public MyClass()
{
   InitializeComponent();

   SetBinding(MyDataContextProperty, new Binding());
}

private static readonly DependencyProperty MyDataContextProperty =
        DependencyProperty.Register("MyDataContext",
                                    typeof(object),
                                    typeof(MyClass),
                                    new PropertyMetadata(DataContextChanged));

private static void DataContextChanged(
            object sender,
            DependencyPropertyChangedEventArgs e)
{
  MyClass source = (MyClass)sender;
  source.OnDataContextChanged();
}

private void OnDataContextChanged()
{
  // My DataContext has changed; do whatever is needed.

  // re 'render' in your case?
}
Royston Shufflebotham