如何具有与OnPropertyChanged一起使用的UserControl的可绑定属性 [英] How to have bindable properties of a UserControl which work with OnPropertyChanged

查看:107
本文介绍了如何具有与OnPropertyChanged一起使用的UserControl的可绑定属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我知道需要创建与属性绑定,我在做这个。



我假设我的用户控件必须实现一个界面,或者属性需要用某些属性来修饰,或者是这些属性的东西。但是我的研究已经到了空白。



应该如何实现?目前我正在通过调用OnValidating()在我的用户控件,当一个属性改变,但似乎不正确。



如果我在UserControl中设置CausesValidation为true,我可以进行验证,但对我来说并不是很有用。



请注意,这是一个 WinForms 情况。



编辑:显然我没有任何解释的才华,希望这将澄清我在做什么。这是一个简写的例子:

  //我有一个用户控件
public class MyControl:UserControl
{
//我绑定到这个属性
public string ControlProperty {get;组; }

public void DoSomething()
{
//当属性值更改时,更改应立即应用于
//到绑定的数据源
ControlProperty =new value;

//这是我如何使其工作,但似乎错误
OnValidating();
}
}

//绑定到usercontrol的类
public class MyDataSource:INotifyPropertyChanged
{
private string sourceProperty;
public string SourceProperty
{
get {return sourceProperty; }
set
{
if(value!= sourceProperty)
{
sourceProperty = value;
NotifyPropertyChanged(SourceProperty);
}
}
}

//样板材料
公共事件PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string info)
{
if(PropertyChanged!= null)
PropertyChanged(this,new PropertyChangedEventArgs(info));
}
}

public class MyForm:Form
{
private MyControl myControl;
public MyForm()
{
//创建数据源
var dataSource = new MyDataSource(){SourceProperty =test};

//将数据源的属性绑定到usercontrol的属性
myControl.DataBindings.Add(ControlProperty,dataSource,SourceProperty,
false,DataSourceUpdateMode。 OnPropertyChanged); //注意更新模式
}
}

(我已经尝试过使用BindingSource,但结果是一样的。)



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



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

解决方案

我想我已经弄清楚了。我不明白如何将变更通知从控件发送到绑定的数据源。



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



从我拼接在一起,控件可以通过两种方式通知数据源属性已更改。



一种方法是控制实现INotifyPropertyChanged。我从来没有从控制端这样做过,我只想到绑定的数据源端必须实现它。



当我在用户控件上实现了INotifyPropertyChanged,并在适当的时候调用了PropertyChanged事件,它的工作正常。



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



对于我的例子,它将是



公共事件EventHandler ControlPropertyChanged



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



我未能注意到MSDN 文档,其中说明如下:


要更改通知发生在
绑定客户端和
数据源之间的绑定,绑定类型应该
或者:



实现INotifyPropertyChanged
接口(首选)。



为绑定类型的每个
属性提供更改事件。


第二种方式是所有现有WinForms控件的工作原理,所以这就是我现在所做的工作。我在我的数据源上使用INotifyPropertyChanged,但是在我的控件上提出了更改的事件。这似乎是传统的方式。


I have a simple usercontrol (WinForms) with some public properties. When I use this control, I want to databind to those properties with the DataSourceUpdateMode set to OnPropertyChanged. The datasource is a class which implements INotifyPropertyChanged.

I'm aware of the need to create bindings against the properties and I'm doing that.

I assumed that my usercontrol would have to implement an interface, or the properties would need to be decorated with some attribute, or something along those lines.But my research has come up blank.

How should this be accomplished? At the moment I'm doing it by calling OnValidating() in my usercontrol whenever a property changes, but that doesn't seem right.

I can get validation to happen if I set the CausesValidation to true on the usercontrol, but that's not very useful to me. I need to validate each child property as it changes.

Note this is a WinForms situation.

EDIT: Evidently I have no talent for explanation so hopefully this will clarify what I'm doing. This is an abbreviated example:

// 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
    }
}

(I have tried this using a BindingSource, but the result was the same.)

Now what I want to happen is that when the value of MyControl.ControlProperty changes, the change is immediately propagated to the datasource (the MyDataSource instance). To achieve this I call OnValidating() in the usercontrol after changing the property. If I don't do that, I have to wait until validation gets triggered by a focus change, which is the equivalent of the "OnValidation" update mode, rather than the desired "OnPropertyUpdate" validation mode. I just don't feel like calling OnValidating() after altering a property value is the right thing to do, even if it (kind of) works.

Am I right in assuming the calling OnValidating() is not the right way to do this? If so, how do I notify the datasource of the ControlProperty change?

解决方案

I think I've got this figured out. I didn't understand how change notifications were sent from control to bound datasource.

Yes, calling OnValidating() is the wrong way.

From what I've pieced together, there are two ways a control can notify the datasource that a property has changed.

One way is for the control to implement INotifyPropertyChanged. I had never done this from the control side before, and I thought only the datasource side of the binding had to implement it.

When I implemented INotifyPropertyChanged on my user control, and raised the PropertyChanged event at the appropriate time, it worked.

The second way is for the control to raise a specific change event for each property. The event must follow the naming convention: <propertyname>Changed

e.g. for my example it would be

public event EventHandler ControlPropertyChanged

If my property was called Foo, it would be FooChanged.

I failed to notice the relavent part of the MSDN documentation, where it says:

For change notification to occur in a binding between a bound client and a data source, your bound type should either:

Implement the INotifyPropertyChanged interface (preferred).

Provide a change event for each property of the bound type.

This second way is how all existing WinForms controls work, so this is how I'm doing it now. I use INotifyPropertyChanged on my datasource, but I raise the Changed events on my control. This seems to be the conventional way.

这篇关于如何具有与OnPropertyChanged一起使用的UserControl的可绑定属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆