我有以下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);
}
}
以下是XAML:
<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>
Constraint是一个定义如下的类:
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
}
}
然后我在UI中有以下ItemsControl:
<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>
当我向Constraint
资源添加constraintCollection
时,ItemsControl
会显示ConstraintBlock
,并在TextBlock
中显示“名称”绑定作为我刚添加的Constraint
的“名称”(属性)。
问题是,当我点击“修改”按钮并调用btnEdit_Click()
时,我会在NullReferenceException
行上获得MessageBox
- 某种方式Constraint
属性ConstraintBlock
对象为空,即使我已(尝试)在Constraint="{Binding}"
的XAML中使用ItemsControl
进行设置。
这种绑定有什么问题?
答案 0 :(得分:2)
没有好的Minimal, Complete, and Verifiable code example,很难肯定。您尚未显示Constraint
类型的内容,也未提供ConstraintBlock_EditClicked
的实施。
尽管如此,我在您的代码中看到的最明显的问题是您尚未正确实现您的Constraint
依赖项属性。您注册了该属性,但您的getter和setter具有默认实现,而不是分别调用GetValue()
和SetValue()
。没有参与依赖属性系统,任何时候WPF尝试直接通过DependencyProperty
值而不是通过属性getter和setter来使用属性,都不会有任何有用的事情发生。
这与获取NullReferenceException
一致,假设Constraint
是引用类型。因为依赖属性的实际值就WPF而言仍然是null
,所以你得到了例外。
如果我的理论是正确的,改变你的房产实施将解决问题:
public Constraint Constraint
{
get { return (Constraint)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}