Dan dot net
Dan dot net

Reputation: 6499

WPF MVVM User Control binding issues

I have an application that uses MVVM. I have several items on the main window that bind to the ViewModel for that window. When I run it everything works. However, when I add a user control to the main window and try to bind to one of its dependency objects it throws an exception (“Object reference not set to an instance of an object”). The exception window just pops up on the screen and does not link to any particular place in code. And any other information in the exception is not helpful.

I’ve tried my best to trace this down but I’m not having any luck. In the constructor of window I’ve checked and verified that the item that it’s attempting to bind to exists and is an object (int[]). I’ve also manually set the property in the constructor with problems. Here are some code snippets if anyone can notice anything.

Here is where I use the user control and attempt to bind to the 'view' property

<local:Histogram Grid.Row="2" Grid.ColumnSpan="2"
                                        View="{Binding Path=HistogramData}"             
                                        Foreground="{DynamicResource FontColor}"
                                        BucketStroke="{DynamicResource BucketStrokeBrush}"
                                        BucketFill="{DynamicResource BucketFillBrush}"
                                        SelectedBrush="{DynamicResource FamilyEditListViewSelectedBrush}"
                                        DisabledForegroundBrush="{DynamicResource DisabledForegroundBrush}"
                                        AxisBrush="{DynamicResource AxisBrush}" 
                                        MaxHeight="130" />

Here is the field in the view model that I am attempting to bind to:

public int[] HistogramData
    {
        get
        {
            return histogramData;
        }
        set
        {
            if (value != histogramData)
            {
                histogramData = value;
                RaisePropertyChanged("HistogramData");
            }
        }
    }

And in the constructor of the view model I instantiate the object

histogramData = new int[256];

And finally here is the view property in the user control

public static readonly DependencyProperty ViewProperty =
        DependencyProperty.Register("View", 
                                    typeof(int[]), 
                                    typeof(Histogram),
                                    new FrameworkPropertyMetadata(null,
                                                                  FrameworkPropertyMetadataOptions.AffectsRender,
                                                                  new PropertyChangedCallback(ViewProperty_Changed)));

    public int[] View
    {
        get { return (int[])GetValue(ViewProperty); }
        set { SetValue(ViewProperty, value); }
    }

I don't know if this is enough information to solve anything so if more code is req please let me know. I could also zip up the project if someone is so inclined to look at that. Thanks in advance.

Upvotes: 2

Views: 3934

Answers (2)

Kent Boogaart
Kent Boogaart

Reputation: 178630

Use the debugger to get an exception stack trace. That should help you narrow the problem down.

There are several ways to do this. For example, you should be able to just view the details of the exception. Or you could open a watch window and enter the expression $exception and then hit evaluate.

Upvotes: 1

David Turvey
David Turvey

Reputation: 2941

You could try initialising the array when you initialise FrameworkPropertyMetaData on the dependency property.

 new FrameworkPropertyMetadata(new int [256],
                              FrameworkPropertyMetadataOptions.AffectsRender,  
                              new PropertyChangedCallback(ViewProperty_Changed))

I think that the program might be hitting a null reference exception before it manages to bind the dependency property to the viewmodel property.


Ok I've had a look at your example project and think i have a solution.

change the int[] in the viewmodel to a List<int>. I'm not sure why this works. I hope there is no technical reason that list<int> is not suitable for you.

Here is what I have changed in the solution

in the viewmodel

public List<int> CustomData
        {
            get
            {
                return new List<int>(){0,1,2,3};
            }
            set
            {
            }
        }

In the arraycontrol codebehind

public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data",
                                        typeof(List<int>),
                                        typeof(ArrayControl),
                                        new FrameworkPropertyMetadata(new List<int>()));

        public List<int> Data
        {
            get { return (List<int>)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

In arraycontrol.xaml. Just added listbox to show data binding working

<UserControl x:Class="UserControlWithArray.Controls.ArrayControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
             <TextBlock x:Name="MessageTextBlock" Text="ArrayControl"/> 
        <ListBox ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Data}"/>
    </Grid>
</UserControl>

Upvotes: 2

Related Questions