Silverlight 5 Prism 4 random error

Topics: Prism v4 - Silverlight 4
Nov 4, 2011 at 6:13 AM

I am having a strange  problem with my implementation of prism. I am doing the following:

(1) Load a View in a Region (using EventAggregator to send message to a class that manages loading/clearing Views in Region)

(2) Load data in to the created View (again using EventAggregator to send and populate the data in the newly created View)

(3) I have a base class for my Views. In this base class, I am trying to access the parent of the View (using VisualTreeHelper.GetParent). This I am doing in an EventHandler (method) that is called when the datacontext of the View is changed

The problem is VisualTreeHelper.GetParent gives me 'null' sometimes, and the proper container on other times. Again, this is quite random.

While debugging, I found that the View is correctly getting loaded in the intended Region even when VisualTreeHelper.GetParent returns null.

Any help will be a blessing to me.

Thanks in advance,

Dharmesh

Developer
Nov 4, 2011 at 12:24 PM

Dharmesh,

Based on my understanding of your scenario, this might be happening due to a timing issue. That is to say, there might be some times in which the DataContext is set on your view while it's still not loaded in the visual tree (in which case the VisualTreeHelper.GetParent method will be returning null), and some other times where it is already loaded in the visual tree (in which case it will return the correct parent). You could try hooking to some other event less likely to be affected by this timing factor.

I hope you find this helpful.

Guido Leandro Maliandi 
http://blogs.southworks.net/gmaliandi

Nov 6, 2011 at 9:45 PM
Edited Nov 6, 2011 at 10:42 PM

Thanks Guido, however is there any way I can 'wait and watch' in code till the loading in the visual tree is finished?

 

So my base class for view is like:

 

  public ViewBase()
        {
            this.DataContextChanged += new DependencyPropertyChangedEventHandler(ViewBase_DataContextChanged);            
        }

protected void ViewBase_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {            
            if (e.NewValue is ViewModelBase)
            {
                SetBinding(IsViewBusyProperty, new Binding() { Source = ((ViewModelBase)e.NewValue).IsFormBusy, Mode= BindingMode.OneWay});
            }
        }


public static readonly DependencyProperty IsViewBusyProperty = DependencyProperty.Register("IsViewBusy", typeof(Boolean), typeof(ViewBase), new PropertyMetadata(new PropertyChangedCallback(OnIsViewBusyChanged)));


public static void OnIsViewBusyChanged(DependencyObject element, DependencyPropertyChangedEventArgs e)
        {            
            DependencyObject parent = VisualTreeHelper.GetParent(element);            
                         
            while (!(parent is PodControl))
            {
                if (parent == null) { break; }
                parent = VisualTreeHelper.GetParent(parent);
            }
            if (parent != null)
            {
                ((PodControl)parent).podBusyIndicator.IsBusy = (bool)e.NewValue;
            }
        }

 

 

So in OnIsViewBusyChanged above, the behavior of VisualTreeHelper.GetParent is random.

 


My View is:

 

    public partial class ParticipantDetailsView : ViewBase, IParticipantDetailsView
    {
        public ParticipantDetailsView(ParticipantDetailsViewModel model)
        {
            InitializeComponent();

            this.Loaded += (s, e) =>
            {
                this.DataContext = model;                
            };

        }
    }
    public interface IParticipantDetailsView : IView
    {
    }

 

 

 

Nov 7, 2011 at 4:02 AM

I solved it.

I used LayoutUpdated event instead of Loaded event as suggested in:

"Loaded and Control Object Lifetime" section in http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded%28v=vs.95%29.aspx

Thanks anyways,

Dharmesh

Developer
Nov 7, 2011 at 11:27 AM

Hi,

I'm glad that you solved your problem, and thanks for sharing it with the rest of the community.

Thanks,

Guido Leandro Maliandi 
http://blogs.southworks.net/gmaliandi