这些是在UserControl中实现简单数据绑定的所有要求

本文关键字:数据绑定 简单 实现 UserControl | 更新日期: 2023-09-27 18:27:28

为了创建一个支持简单数据绑定的自定义控件,我遵循了微软在这里报告的说明,并且在我发现它们不完整后不久。实现DefaultBindingProperty属性是不够的,您似乎需要控制(i)实现INotifyPropertyChanged或公开名为<propertyname>Changed的事件,如这里所解释的。

尽管如此,我下面的代码(实际上是它的一个非常简化的版本)仍然不起作用,我已经为此挣扎了将近一天。我的控制是:

[DefaultBindingProperty("Value")]
public partial class MyUserControl : UserControl
{
    NumericUpDown upDown;
    public MyUserControl()
    {
        InitializeComponent();
        upDown = new NumericUpDown() { Minimum = 0, Maximum = 100, Dock = DockStyle.Fill };
        Controls.Add(upDown);
        upDown.ValueChanged += control_ValueChanged;
    }
    [Bindable(true)]
    public double Value
    {
        get { return (double)upDown.Value; }
        set { upDown.Value = (decimal)value; }
    }
    private void control_ValueChanged(object sender, EventArgs e)
    {
        if (ValueChanged != null)
            ValueChanged(this, e);
    }
    public event EventHandler<EventArgs> ValueChanged;
}

和我的测试表格:

public partial class Form1 : Form
{
    MyUserControl myUserControl;
    BindingSource source;
    MyClass myClass;
    public Form1()
    {
        InitializeComponent();
        source = new BindingSource();
        myClass = new MyClass() { Amount = 30 };
        source.DataSource = new[] { myClass };
        myUserControl = new MyUserControl();
        Controls.Add(myUserControl);
        myUserControl.DataBindings.Add("Value", source, "Amount", false, DataSourceUpdateMode.OnPropertyChanged);
    }
}
public class MyClass
{
    int amount;
    public int Amount
    {
        get { return amount; }
        set
        {
            amount = value;
            MessageBox.Show("New amount: " + amount);
        }
    }
}

在更改NumericUpDown中的值时,不会触发代码末尾的消息框。还有我遗漏的另一条信息吗?我在这里做错了什么?

这些是在UserControl中实现简单数据绑定的所有要求

似乎需要让控件实现INotifyPropertyChanged或公开名为<propertyName>更改如下。

这些是实现数据源时的选项。对于自定义控件,唯一的选择是后者,因为基本控件已经在使用该模式,并且实现INotifyPropertyChanged将破坏它,因为正如的一个注释所述

为了在绑定客户端和数据源之间的绑定中发生更改通知,您的绑定数据源类型应实现INotifyPropertyChanged接口(首选),或者您可以为绑定类型提供propertyNameChanged事件,但不应同时执行这两种操作。

所以你正确地使用了PropertyNameChanged模式(或者至少尝试过:)

还有我遗漏的另一条信息吗?我在这里做错了什么?

以下是一些相关链接-Windows窗体数据绑定中的更改通知和如何:应用PropertyNameChanged模式,但您缺少的是PropertyNameChanged模式到底是什么,不幸的是,文档中的任何地方似乎都没有解释,关键是,除了特别命名的事件外,它还需要该事件的特定类型,更确切地说是EventHandler类型。我想现在你看到问题了——你已经使用了EventHandler<EventArgs>。方法签名是相同的,但对于Action<object, EvenetArgs>可以说是相同的。EventHandler<TEventArgs>现在是推荐的,但请记住,在引入数据绑定时它并不存在。等等

矮子,把这条线换成

public event EventHandler<EventArgs> ValueChanged;

public event EventHandler ValueChanged;

一切都会按预期进行。