timheuer / callisto

A control toolkit for Windows 8 XAML applications. Contains some UI controls to make it easier to create Windows UI style apps for the Windows Store in accordance with Windows UI guidelines.
http://timheuer.com/blog/archive/2012/05/31/introducing-callisto-a-xaml-toolkit-for-metro-apps.aspx
Other
338 stars 108 forks source link

using callisto in xaml/cs grid project template is throwing null reference exception #176

Open myusrn opened 11 years ago

myusrn commented 11 years ago

I am using callisto in xaml/cs grid project template setup where i'm trying to instantiate it from the Loaded event. If try and set settings.IsOpen = true then following exception and message. If I leave settings.IsOpen commented out all is well but the flyout doesn't render.

Exception {"Object reference not set to an instance of an object."} Message "System.NullReferenceException\r\n at Callisto.Controls.SettingsFlyout.OnLoaded(Object sender, RoutedEventArgs e)"

public GroupedItemsPage() { this.InitializeComponent(); this.Loaded += GroupedItemsPage_Loaded; }

async void GroupedItemsPage_Loaded(object sender, RoutedEventArgs e) { SettingsFlyout settings = new SettingsFlyout(); settings.FlyoutWidth = Callisto.Controls.SettingsFlyout.SettingsFlyoutWidth.Wide; settings.HeaderBrush = new SolidColorBrush(Colors.Blue); settings.HeaderText = "identity provider credentials"; settings.SmallLogoImageSource = new BitmapImage(new Uri("ms-appx:///Assets/SmallLogo.png")); settings.Content = new IdpCredentialsFlyout(); //settings.IsOpen = true; Log.Instance.TraceInformation("idp credentials flyout being displayed");

timheuer commented 11 years ago

Hmm, looks like a race condition...it cannot find the template part.

Workaround...before calling IsOpen:

Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () =>
                {
                    settings.IsOpen = true;
                });
myusrn commented 11 years ago

Thanks that resolved the issue. I guess we see this because we are doing this I Loaded event handler and not some later point in page initialization experience. Would you suggest we just do this with all xaml/cs app settings flyout IsOpen calls or just cases where the unexpected exception arises?

timheuer commented 11 years ago

I wouldn't expect this to even have been needed. I don't think you have to do this everywhere but I do need to find the root cause.

myusrn commented 11 years ago

For repro you can visit http://aka.ms/fedid | winrt project scaffolding | project site | example solution download and run App5. I only found it to be needed in the GetIdpCredentials flyout case and not in the GetIdpSelection case even though I currently have Dispatch now added for both, just in case.

eric-h-st commented 11 years ago

Hi, The problem persists for versions 1.2.6 through 1.2.9 and the offered workaround did not solve it for us.

Looking at the code, it seems that the NullReferenceException is thrown when attempting to set the Width property of the _contentScrollViewer control field, while the field itself is still null. That's within the OnLoaded override is this line:

        // setting all the widths to be the size of flyout
        _hostPopup.Width = this.Width = _contentScrollViewer.Width = _settingsWidth;

That might be caused by attempting to set these fields in the OnApplyTemplate override, and using them on the OnLoaded override, while these two methods are not guaranteed to be called sequentially.

Please see this: http://msdn.microsoft.com/en-ca/library/windows/apps/windows.ui.xaml.frameworkelement.onapplytemplate

"OnApplyTemplate is often a more appropriate point to deal with adjustments to the template-created visual tree than is the Loaded event. The Loaded event might occur before the template is applied, and the visual tree might be incomplete as of Loaded."

Thank you, Erez