views:

280

answers:

2

I've got a subclassed UserControl that is the content for my main window. I added a DepedencyProperty to my usercontrol, of type ResizeMode, and the PropertyChanged callback sets the ResizeMode of the main window to the value correctly. It runs fine. I can set it from the code behind, or from the XAML, and it works correctly. However, when I set it from XAML, the designer throws an Object reference not set to an instance of an object exception, on the code in the PropertyChanged callback that sets the window's resize.

<classes:MyUserControl ResizeMode="NoResize">
     <...>
</classes:MyUserControl>

This is the callback. MainWindow is a reference to the parent window.

private static void OnResizeModeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
     (o as MyUserControl).MainWindow.ResizeMode = (ResizeMode) e.NewValue;
}

public ResizeMode ResizeMode { get { return (ResizeMode) GetValue(ResizeModeProperty); } set { SetValue(ResizeModeProperty, value); } }

public static readonly DependencyProperty ResizeModeProperty =
            DependencyProperty.Register("SizeToFit", typeof(ResizeMode), typeof(MyUserControl),
                new UIPropertyMetadata(ResizeMode.CanResize, new PropertyChangedCallback(OnResizeModeChanged)));

I could ignore it, or set it in the code behind, but I don't really understand the reason for this error, and I would prefer to set it in XAML.

Can anyone shed some light?

A: 

Do you know exactly where the NullReferenceExceptoin is being thrown? For example, if you try this instead:

var uc = o as MyUserControl;
var mw = uc.MainWindow;

mw.ResizeMode = (ResizeMode)e.NewValue;

... then is the exception raised on the second line or the third?

My feeling is that MainWindow has not been assigned by the time ResizeMode is first given a value, so accessing MainWindow.ResizeMode is causing the error.

If that's the case, it's safe to ignore:

var mw = (o as MyUserControl).MainWindow;
if (mw == null) return;

But you might want to cache the value somewhere, and then assign it to MainWindow.ResizeMode when MainWindow gets assigned later.

Matt Hamilton
Yes, it seems to be the ResizeMode causing the trouble. Is there a flag or a property I can set on my dependecy property that tells the XAML parser to not try setting it until the UserControl is actually created?
Kage
A: 

OK, I think I found the culprit. The MainWindow is set by App.Current.MainWindow.

Now from what I've read, the Current.MainWindow doesn't exist in Design time, and then when the OnResizeModeChanged methods fire during designtime, MainWindow.ResizeMode, boom! Exception!

I added this line to my methods:

if ((bool) (DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)) return;

I encountered another problem where my XAML suddenly couldn't load my usercontrol, due to me setting some properties on MainWindow in the constructor, added this:

 if (DesignerProperties.GetIsInDesignMode(this))
          return;
Kage