如何使用与OnPropertyChanged一起使用的UserControl的可绑定属性

时间:2011-07-05 21:20:36

标签: c# .net winforms data-binding user-controls

我有一个带有一些公共属性的简单usercontrol(WinForms)。当我使用此控件时,我想将DataSourceUpdateMode设置为 OnPropertyChanged 的数据绑定到这些属性。数据源是一个实现INotifyPropertyChanged的类。

我知道需要为属性创建绑定,而我正在这样做。

我认为我的usercontrol必须实现一个接口,或者属性需要用某些属性进行修饰,或者沿着那些行进行修饰。但是我的研究空白了。

如何实现这一目标?目前,我正在通过在属性更改时在我的usercontrol中调用OnValidating()来实现它,但这似乎不对。

如果我在用户控件上将CausesValidation设置为true,我可以进行验证,但这对我来说并不是很有用。我需要验证每个子属性的变化。

请注意,这是 WinForms 情况。

编辑:显然我没有解释的天赋,所以希望这会澄清我在做什么。这是一个简短的例子:

// I have a user control
public class MyControl : UserControl
{
    // I'm binding to this property
    public string ControlProperty { get; set; }

    public void DoSomething()
    {
        // when the property value changes, the change should immediately be applied 
        // to the bound datasource
        ControlProperty = "new value";

        // This is how I make it work, but it seems wrong
        OnValidating();         
    }
}

// the class being bound to the usercontrol
public class MyDataSource : INotifyPropertyChanged
{
    private string sourceProperty;
    public string SourceProperty
    {
        get { return sourceProperty; }
        set
        {
            if (value != sourceProperty)
            {
                sourceProperty = value;
                NotifyPropertyChanged("SourceProperty");
            }
        }
    }

    // boilerplate stuff
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

public class MyForm : Form
{
    private MyControl myControl;
    public MyForm()
    {
        // create the datasource 
        var dataSource = new MyDataSource() { SourceProperty = "test" };

        // bind a property of the datasource to a property of the usercontrol
        myControl.DataBindings.Add("ControlProperty", dataSource, "SourceProperty",
            false, DataSourceUpdateMode.OnPropertyChanged); // note the update mode
    }
}

(我使用BindingSource尝试了这个,但结果是一样的。)

现在我想要发生的是,当MyControl.ControlProperty的值发生变化时,更改会立即传播到数据源(MyDataSource实例)。为了实现这一点,我在更改属性后在usercontrol中调用OnValidating()。如果我不这样做,我必须等到焦点更改触发验证,这相当于“OnValidation”更新模式,而不是所需的“OnPropertyUpdate”验证模式。我只是觉得在更改属性值之后调用OnValidating()是正确的,即使它(有点)有效。

我是否正确地假设调用OnValidating()正确的方法?如果是这样,我如何通知ControlProperty更改的数据源?

2 个答案:

答案 0 :(得分:13)

我想我已经搞清楚了。我不明白如何将更改通知从控制发送到绑定数据源。

是的,调用OnValidating()是错误的方法。

从我拼凑的内容中,控件可以通过两种方式通知数据源属性已更改。

一种方法是控件实现INotifyPropertyChanged。我以前从未在控制端做过这个,我认为只有绑定的数据源端必须实现它。

当我在我的用户控件上实现了INotifyPropertyChanged,并在适当的时候引发了PropertyChanged事件时,它运行了。

第二种方法是控件为每个属性引发特定的更改事件。该事件必须遵循命名约定:<propertyname>Changed

e.g。对于我的例子,它将是

public event EventHandler ControlPropertyChanged

如果我的财产被称为Foo,那将是FooChanged

我没有注意到MSDN documentation的相关部分,其中包含:

  

要在a中发生变更通知   绑定客户端和a之间的绑定   数据源,你的绑定类型应该   之一:

     

实施INotifyPropertyChanged   界面(首选)。

     

为每个人提供更改活动   绑定类型的属性。

第二种方式是所有现有的WinForms控件如何工作,所以这就是我现在正在做的事情。我在我的数据源上使用了INotifyPropertyChanged,但是我在我的控件上引发了Changed事件。这似乎是传统方式。

答案 1 :(得分:1)

实现 INotifyPropertyChanged 界面非常简单。以下示例显示了具有单个公共字段的对象...

public class Demo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
    }

    private string _demoField;

    public string DemoField
    {
        get {return demoField; }

        set
        {
            if (value != demoField)
            {
                demoField = value;
                NotifyPropertyChanged("DemoField");
            }
        }
    }
}

然后,您将创建一个Binding实例,将控件属性绑定到源实例(Demo实例)上的属性(DemoField)。