【问题标题】:Binding User Control Properties to ItemsControl将用户控件属性绑定到 ItemsControl
【发布时间】:2016-07-09 23:10:52
【问题描述】:

我有以下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>

约束是一个定义如下的类:

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() 时,我在MessageBox 行上得到一个NullReferenceException - 不知何故,ConstraintBlock 对象的Constraint 属性为空,即使我已经(尝试)在 XAML 中为 ItemsControl 设置了 Constraint="{Binding}"

这个绑定有什么问题?

【问题讨论】:

    标签: c# wpf xaml binding


    【解决方案1】:

    没有好的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); }
    }
    

    【讨论】:

    • 谢谢,彼得 - 它有效!另外,为了清楚起见,我添加了约束类的定义。
    猜你喜欢
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多