views:

163

answers:

3

I'm getting an "Object reference not set to an instance of an object" error when I try to reload the Designer for my XAML UserControl. Visual Studio highlights the following line as being the problem:

<local:TemplateDetail Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3"
    Width="600" TemplateData="{Binding ElementName=cbo_templates,
                               Path=SelectedItem.Data, Mode=OneWay}"/>

TemplateDetail is another UserControl. When I view TemplateDetail, its Designer view loads just fine, so I don't think there's a problem there. There is a ComboBox in my XAML named cbo_templates that contains instances of my Template class, which has a Data property (hence SelectedItem.Data). However, if I remove .Data from the Path in the above XAML, I still get the "Object reference" error, so I don't think the problem is that I'm trying to access the Path property on null. Here's my ComboBox XAML just in case:

<ComboBox ItemsSource="{Binding Path=List}" Grid.Row="1" Grid.Column="3"
          VerticalAlignment="Center" x:Name="cbo_templates" Width="250"
          HorizontalAlignment="Left" DisplayMemberPath="Name"
          SelectedValuePath="Name" SelectedIndex="0"/>

Getting this error is a real problem because the Design view won't load, so I can't see what my UserControl looks like without running the app. Any idea what could be wrong? It builds fine and I don't see any binding problems in the Build Output.

Edit: here is the constructor code for both UserControls:

Constructor of UserControl with "Object reference" error:

InitializeComponent();
grd_templateList.DataContext = this; // refers to containing <Grid> in XAML

Constructor of UserControl I'm trying to embed, the one whose Design view loads okay:

InitializeComponent();
grd_templateDetail.DataContext = this; // refers to containing <Grid> in XAML

Edit: I tried putting an if (null != grd_templateList) check in the constructors before setting their DataContext properties, but that didn't help--still getting the "Object reference" error when reloading the Designer.

Edit: the List property that the ComboBox uses is a DependencyProperty. I have a default value set in the Register method:

public static readonly DependencyProperty ListProperty =
    DependencyProperty.Register(
        "List",
        typeof(List<Template>),
        typeof(TemplateList),
        new PropertyMetadata(
            new List<Template> { _defaultTemplate }
        )
    );

Even if I try to initialize List in the constructor for my UserControl, I still get the error when reloading the Designer. I don't think the problem is that List is null or SelectedItem.Data is a bad path.

Edit: okay, even just having this causes my Designer to not load, giving the "Object reference" error:

<local:TemplateDetail Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3"
                      TemplateData="{Binding}"/>

There is something it dislikes about the TemplateData property being bound, apparently.

Edit: to add to the mystery, I can view the Design view of my overall/main Window, which includes the UserControl whose Design view gives me the "Object reference" error. O_o

+4  A: 

If your user control throws exception at design time, you can debug it. To do this, open Dll project with this user control in Visual Studio. Select another Visual Studio instance as executable for debugging. Start debugging. In the second (debugged) Visual Studio instance use your user control in the client XAML page. By this way, you can debug user control in design mode.

Alex Farber
By `select another Visual Studio instance as executable for debugging`, do you mean 'Attach to Process'?
Sarah Vessels
You can use Attach to Process, or open Project Properties, Debugging, executable for debugging session, and fill command line with command starting Visual Studio. Then execute "Start Debug" command. Another VS instance starts. In this instance, use user control on the client form or XAML page.
Alex Farber
NVM below explained how to go about doing this, but as I said in comments there, I can't get the second instance of VS 2010 to show any error messages about the "Object reference" error.
Sarah Vessels
Do you mean, that in standalone Visual Studio instance you can get exception, and in debugger instance it is not reproduced? Just do in debugged instance the same, as you do in standalone instance. You can also add Trace.WriteLine calls to the control code, testing for NULL different objects before using them. Catch this output with DbgView program.
Alex Farber
+2  A: 

What Alex says is the easiest way to go. But I think its a little confusing to understand what he is saying.

Assuming you have your project open in VisualStudio, open another VisualStudio instance and select Debug->Attach To Process. In the dialog which opens select devenv.exe(which is the first VS instance). Then do "Reload Designer" for the user control and see the output in the second VS instance to check what exactly is the error.

NVM
Thanks for the clarification. I tried this but nothing shows up in the second VS window (the one where I chose Attach to Process). I hit Reload Designer in my first VS window and it shows the same "Object reference" error in the Error List, but never pops over to the second VS window. Is there a way to set breakpoints in XAML?
Sarah Vessels
Actually I didnt see your xaml before. I think the problem is SelectedItem.Data. SelectedItem is null and you are referencing Data on it. Haha and now I read your text. Sorry!!!
NVM
@NVM: I dunno, even when I remove everything in the `Binding` so that it only says `Binding ElementName=cbo_templates`, I get the error.
Sarah Vessels
Ok on a couple of very rare ocassions I have found that when the second VS instance doesnt show anything. Restarting the project in VS magically solves the problem. This is a shot in the dark though.
NVM
@NVM: exiting VS, opening two instances, Attaching to the first, opening my project in the first, and then reloading the Designer still doesn't pop me over to the second VS or show anything at all in the second VS. :( I'm using VS 2010 if it matters.
Sarah Vessels
The Debug Output in the second VS instance says a bunch of stuff like 'devenv.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\assembly\GAC\EnvDTE90\9.0.0.0__b03f5f7f11d50a3a\EnvDTE90.dll', but nothing specific to my project that I see.
Sarah Vessels
I think this problem in itself is worth understanding. Anyway having a closer look at your code my instinct(experience) tells me new PropertyMetadata( new List<Template> { _defaultTemplate } ) is a problem. http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7d8dae8b-7078-49da-8dd1-7e1e57f9f10eSince the property is static its probably a clue as to why the second VS instance shows nothing. These are not very educated guesses though.
NVM
@NVM: I tried removing the `new PropertyMetadata` entirely, but that didn't help. I then tried just initializing a `new Template` in the `PropertyMetadata` constructor, but still the same problem. I'm looking around for how to debug design-time WPF.
Sarah Vessels
+1  A: 

It's probably something in the constructor of your user controls. VS2008 WPF designer appears have some issues with this.

In a project we took over, we added:

if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
    return;
}

to the beginning of the constructor of the user controls where this happens to avoid that error.

Chris Persichetti