1

I have the following UserControl:

public partial class ConstraintBlock : UserControl
{
    public static readonly DependencyProperty LabelProperty =
        DependencyProperty.Register("Constraint", typeof(Constraint)
            , typeof(ConstraintBlock));

    public Constraint Constraint { get; set; }

    public event EventHandler EditClicked;

    public ConstraintBlock()
    {
        InitializeComponent();
    }

    private void btnEdit_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(Constraint.ToString());
        if (this.EditClicked != null) this.EditClicked(this, e);
    }
}

Here is the XAML for it:

<UserControl x:Class="MyApp.Controls.ConstraintBlock"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MyApp.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="60" d:DesignWidth="500">
    <Grid Margin="5">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="25" />
                <RowDefinition Height="25" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <TextBlock x:Name="tbName" Grid.RowSpan="2" Text="{Binding Name}" />
            <Button x:Name="btnEdit" Grid.Row="1" Click="btnEdit_Click" />
        </Grid>
    </Grid>
</UserControl>

A Constraint is a class defined as follows:

namespace MyApp.Classes
{
    public class Constraint
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public ConstraintObject Object { get; set; }
        public ConstraintClause Clause { get; set; }
        public Nullable<ConstraintOperator> Operator { get; set; }
        public string Expression { get; set; }
    }

    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    public enum ConstraintObject
    {
        Expression,
        [Description("File Extension")]
        FileExtension,
        [Description("File Name")]
        FileName
    }

    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    public enum ConstraintClause
    {
        Contains,
        [Description("Does Not Contain")]
        DoesNotContain,
        Date,
        Length,
        Like,
        [Description("Not Like")]
        NotLike,
        Number
    }

    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    public enum ConstraintOperator
    {
        [Description("=")]
        EqualTo,
        [Description(">")]
        GreaterThan,
        [Description("<")]
        LessThan,
        [Description(">=")]
        GreaterThanOrEqualTo,
        [Description("<=")]
        LessThanOrEqualTo
    }
}

I then have the following ItemsControl in the UI:

<ItemsControl x:Name="constraintStack" ItemsSource="{StaticResource constraintCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <ctrls:ConstraintBlock Constraint="{Binding}" Grid.Row="2"
                                       EditClicked="ConstraintBlock_EditClicked"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

When I add a Constraint to the constraintCollection resource, the ItemsControl shows the ConstraintBlock, and also shows the "Name" binding in the TextBlock as the "Name" (property) of the Constraint I just added.

The problem is that when I click the "Edit" button and btnEdit_Click() is called, I get a NullReferenceException on the MessageBox line - somehow the Constraint property of the ConstraintBlock object is null, even though I have (attempted to) set this with Constraint="{Binding}" in the XAML for the ItemsControl.

What is wrong with this binding?

1 Answer 1

2

Without a good Minimal, Complete, and Verifiable code example it's difficult to say for sure. You haven't shown what the Constraint type is, nor have you provided the implementation for ConstraintBlock_EditClicked.

That said, the most obvious problem I see in your code is that you haven't implemented your Constraint dependency property correctly. You register the property, but your getter and setter have their default implementation instead of calling GetValue() and SetValue(), respectively. Without participating in the dependency property system, any time WPF attempts to use the property via the DependencyProperty value directly instead of through the property getter and setter, nothing useful will happen.

This is consistent with getting a NullReferenceException, assuming Constraint is a reference type. Since the dependency property's actual value remains null as far as WPF is concerned, you get the exception.

If my theory is correct, changing your property implementation will fix the problem:

public Constraint Constraint
{
    get { return (Constraint)GetValue(LabelProperty); }
    set { SetValue(LabelProperty, value); }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, Peter - it works! Also, I added the definition of a Constraint class in for clarity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.