几个使用的例子INotifyPropertyChanged使用标准公共事件的接口和实现。
相关文档:
Windows 窗体数据绑定
Windows 窗体数据绑定中的更改通知
数据绑定相关接口
Using INotifyPropertyChanged
:
UserControl 公开了一个公共属性(此处名为CustomDataObject
, 简单的string
输入第一个示例,object
在第二。当然它可以是另一种类型)。
该物业的装饰有Bindable属性。这BindingDirection
这里还有一个意图描述,没有附加模板。
添加了另外两个标准属性:
-
默认值定义属性的默认值(创建控件时分配给属性的值)。代码生成器使用它来确定当前值是否应该序列化:如果它与属性设置的值匹配,则不会序列化。
PropertyGrid 还使用它以粗体显示非默认值选择或分配。
-
设计师序列化可见性指定属性应如何在设计时序列化。这里,设置为DesignerSerializationVisibility.Visible,表示该属性应该被序列化。
The INotifyPropertyChanged
接口可以被视为一种简化的方法,使用相同的事件处理程序将属性绑定添加到多个属性,以通知值的更改。
接口的默认实现只需要一个公共事件类型属性更改事件处理程序被添加到类中。
当属性值更改时,设置器仅调用事件。执行此操作的方法略有不同;在这里我用的是OnPropertyChanged()
方法使用来电者姓名归因于acquire调用它的属性的名称。它在 WinForms 和 WPF 中相当常见。
UCA用户控制:
UserControl(参见视觉示例)有两个可以更改绑定的按钮CustomDataObject
适当的价值。他们的Click
动作由ButtonsAction_Click
.
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
public partial class UCA : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string m_DataObject = string.Empty;
public UCA() => InitializeComponent();
[Bindable(true, BindingDirection.TwoWay), DefaultValue("")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string CustomDataObject {
get => m_DataObject;
set {
if (m_DataObject != value){
m_DataObject = value;
OnPropertyChanged();
}
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private void ButtonsAction_Click(object sender, EventArgs e)
{
var btn = sender as Button;
CustomDataObject = (btn == SomeButton) ? txtInput1.Text : txtInput2.Text;
}
}
UCB 用户控制:
这个另一个 UserControl 是receiver。它只是暴露了一个公共属性(ReceiverDataObject
)将绑定到CustomDataObject
UCA 的财产。
The ReceiverDataObject
属性也定义为[Bindable]
,与意图使其成为单向的。该属性不会引发任何事件。它接收一个值,将其存储在私有字段中并设置内部 UI 元素。
public partial class UCB : UserControl
{
private string m_RecvDataObject = string.Empty;
public UCB() => InitializeComponent();
[Bindable(true, BindingDirection.OneWay)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string ReceiverDataObject {
get => m_RecvDataObject;
set {
m_RecvDataObject = value;
txtPresenter.Text = m_RecvDataObject;
}
}
}
使用标准事件通知:
您还可以使用标准事件生成属性更改通知。
不同之处在于,每个属性都需要一个事件来通知更改。
如果您已经为此使用了事件委托,那么它可能是一个不错的选择,因为需要添加的内容很少:只需调用在属性设置器中引发事件的受保护方法即可。
在这里,我使用常见的 .Net 事件处理,使用事件处理器列表由底层 Component 类定义并由其公开Events属性,以添加删除事件订阅。
通常会调用与事件同名的受保护方法来引发事件,但On
prefix.
Here, CustomDataObjectChanged
活动 =>OnCustomDataObjectChanged()
method.
您可以在所有标准控件中看到这种模式。
▶ The CustomDataObjectChanged
分配给事件的名称不是一个选择:该事件必须与属性和属性具有相同的名称Changed
suffix.
这就是模式,遵循它就足够了。
UCA用户控制:
public partial class UCA : UserControl
{
private static readonly object Event_CustomDataObjectChanged = new object();
private object m_DataObject = null;
public UCButtonActions() => InitializeComponent();
[Bindable(BindableSupport.Yes, BindingDirection.TwoWay), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public object CustomDataObject {
get => m_DataObject;
set {
if (m_DataObject != value){
m_DataObject = value;
OnCustomDataObjectChanged(EventArgs.Empty);
}
}
}
public event EventHandler CustomDataObjectChanged {
add {
Events.AddHandler(Event_CustomDataObjectChanged, value);
}
remove {
Events.RemoveHandler(Event_CustomDataObjectChanged, value);
}
}
protected virtual void OnCustomDataObjectChanged(EventArgs e)
{
if (Events[Event_CustomDataObjectChanged] is EventHandler evth) evth(this, e);
}
}
UCB 用户控制:
第二个 UserControl 不变。这只是接收器。
Form 类(或用作 Handler 的另一个类):
在表单构造函数或表单初始化后调用的任何其他方法中,使用数据绑定UCB 属性来链接两个 UserControl 的属性:
public SomeForm()
{
InitializeComponent();
ucb1.DataBindings.Add("ReceiverDataObject", uca1, "CustomDataObject",
false, DataSourceUpdateMode.OnPropertyChanged);
}
您还可以使用 BindingSource 进行调解:
BindingSource ucsSource = null;
public SomeForm()
{
InitializeComponent();
ucsSource = new BindingSource(uca1, null);
ucb1.DataBindings.Add("ReceiverDataObject", ucsSource, "CustomDataObject",
false, DataSourceUpdateMode.OnPropertyChanged);
}
示例功能: