locked
System.Runtime.InteropServices.COMException when calling UpdateLayout()

    Question

  • I have an ItemsControl for which I set the ItemsSource property and attempt to access items using the VisualTreeHelper. Here is my code from my page's Loaded event:

    Me.itmRecipients.ItemsSource = Me.Recipients.Select(Function(r, i) New With {.Name = r.Name, .Index = i})
    Me.itmRecipients.UpdateLayout()
    Dim selectedradiobutton As RadioButton = CType(VisualTreeHelper.GetChild(Me.itmRecipients.ContainerFromIndex(Me.SelectedRecipientIndex), 0), RadioButton)

    The error occurs when I call UpdateLayout(), and I get the following:

    System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.
       at Windows.UI.Xaml.UIElement.UpdateLayout()
       at GiftTrackerUnivAppTest_Windows.MainPage.MainPage_Loaded(Object sender, RoutedEventArgs e)

    I am calling UpdateLayout() so that I can use the VisualTreeHelper. Why am I receiving this error? Thanks.


    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Tuesday, January 6, 2015 3:33 AM

All replies

  • If you make that same call later in the page lifetime (perhaps in a button click event), does it have the same error? I am wondering if the layout hasn't yet completed.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Tuesday, January 6, 2015 2:11 PM
    Moderator
  • OK, I tried that, so it doesn't give the error now and does what I need when I click the Button. After moving it to the LayoutUpdated event it seems good. But I am still having another problem (I'm not sure if it is related or not). My current code is now the following:
    Private Sub MainPage_LayoutUpdated(sender As Object, e As Object) Handles Me.LayoutUpdated
    	Me.itmRecipients.UpdateLayout()
    	Dim temp As DependencyObject = Me.itmRecipients.ContainerFromIndex(Me.SelectedRecipientIndex)
    	Dim selectedradiobutton As RadioButton = CType(VisualTreeHelper.GetChild(Me.itmRecipients.ContainerFromIndex(Me.SelectedRecipientIndex), 0), RadioButton)
    	If Me.Recipients.Any() Then CType(VisualTreeHelper.GetChild(Me.itmRecipients.ContainerFromIndex(Me.SelectedRecipientIndex), 0), RadioButton).IsChecked = True
    End Sub
    
    Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    	Me.itmRecipients.ItemsSource = Nothing
    	Me.itmGifts.ItemsSource = Nothing
    	Me.cntDetails.Content = Nothing
    	Me.itmRecipients.ItemsSource = Me.Recipients.Select(Function(r, i) New With {.Name = r.Name, .Index = i})
    End Sub
    When I run this code, LayoutUpdated is called before I set ItemsSource (the last line of the Loaded event), therefore temp (the second line of LayoutUpdated) ends up being Nothing, which means I will receive an error when using the VisualTreeHelper. I do not want to put more code than necessary (such as setting ItemsSource) in the LayoutUpdated event, because this is code that I only want run once (which is why I originally had it in the Loaded event). How can I solve this without worrying about it being run more than once? Thanks.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Tuesday, January 6, 2015 5:55 PM
  • I don't know if it is the best (or even necessarily correct) solution, but if I call UpdateLayout() from both the LayoutUpdated AND Loaded events, it seems to work:
    Private Sub MainPage_LayoutUpdated(sender As Object, e As Object) Handles Me.LayoutUpdated
    	Me.itmRecipients.UpdateLayout()
    End Sub
    
    Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    	'Set ItemsSource & Content
    	Me.itmRecipients.ItemsSource = Nothing
    	Me.itmGifts.ItemsSource = Nothing
    	Me.cntDetails.Content = Nothing
    	Me.itmRecipients.ItemsSource = Me.Recipients.Select(Function(r, i) New With {.Name = r.Name, .Index = i})
    
    	Me.itmRecipients.UpdateLayout()
    	If Me.Recipients.Any() Then CType(VisualTreeHelper.GetChild(Me.itmRecipients.ContainerFromIndex(Me.SelectedRecipientIndex), 0), RadioButton).IsChecked = True
    End Sub
    So I guess now it is calling UpdateLayout() before AND after I set ItemsSource. Whether this is the correct way to fix it or even one that will always work, I'm not sure. So thanks for your help!

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Tuesday, January 6, 2015 7:03 PM
  • Unfortunately, the problem is back, only this time it is in a Checked event triggered when I set IsChecked=True. I am guessing that this is happening for the same reason as it was before (this time it is a different ItemsControl, but same scenario). I tried to solve the problem using techniques using the LayoutUpdated event like I did before, but it is still not working. I am completely confused about all the UpdateLayout() method, LayoutUpdated event, and how to determine when I am allowed to use things such as ContainerFromIndex and VisualTreeHelper. Are there any good sites or blogs about these things? Any help would be appreciated. Thanks.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Wednesday, January 7, 2015 11:00 PM
  • Can you provide a sample so I can test it?

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Monday, January 12, 2015 1:08 PM
    Moderator