[英]c# Notify parent property from child
我有以下课程:
public class child
{
public string product { get; set; }
public decimal amount { get; set; }
public decimal price { get; set; }
public decimal total { get; set; }
}
public class parent
{
public decimal total { get; set; }
public BindingList<child> childs { get; set; }
}
现在,在 windows 表单中,我设置以下内容:
var parent_object = new parent();
numericUpDown1.DataBindings.Add("Value", parent_object , "total", true, DataSourceUpdateMode.OnPropertyChanged);
dataGridView1.DataBindings.Add("DataSource", parent_object , "childs", true, DataSourceUpdateMode.OnPropertyChanged);
最后(我不知道该怎么做), parent 的总属性在以下情况下会自动更改:
谢谢你的帮助。
到目前为止,您的代码看起来很合理,除了在连接所有内容方面缺少一些部分,因此我将提供一些建议。 第一个是简化DataGridView
的数据绑定,您需要的只是dataGridView.DataSource = childs
。 如果您除了通过覆盖MainForm.OnLoad
来初始化它之外什么都不做,那么您已经有了一个看起来不错的视图(但它会缺少双向交互)。
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
dataGridView.DataSource = childs;
// Add one or more child items to autogenerate rows.
childs.Add(new child
{
product = "GEARWRENCH Pinch Off Pliers",
price = 27.10m,
amount = 1.0m
});
childs.Add(new child
{
product = "AXEMAX Bungee Cords",
price = 25.48m,
amount = 1.0m
});
// Format rows
foreach (DataGridViewColumn column in dataGridView.Columns)
{
switch (column.Name)
{
case nameof(child.product):
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
break;
default:
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
column.DefaultCellStyle.Format = "F2";
break;
}
}
}
private readonly BindingList<child> childs = new BindingList<child>();
private readonly parent parent_object = new parent();
可绑定属性
为了创建支持双向通信的绑定属性,您需要一种方法来检测和通知属性何时发生变化。 例如,要使parent
class 中的total
属性可绑定,请执行以下操作:
public class parent : INotifyPropertyChanged
{
decimal _total = 0;
public decimal total
{
get => _total;
set
{
if (!Equals(_total, value))
{
_total = value;
OnPropertyChanged();
}
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
numericUpDown
代码中显示的数据绑定现在将响应total
的更改。
numericUpDown.DataBindings.Add(
nameof(numericUpDown.Value),
parent_object,
nameof(parent_object.total),
false,
DataSourceUpdateMode.OnPropertyChanged);
内部响应变化
通过使用上面的示例以相同的方式使child
class 中的所有属性可绑定后,请考虑采用在内部处理某些更改的方法,在这种情况下,您将禁止触发属性更改通知。
public class child : INotifyPropertyChanged
{
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
switch (propertyName)
{
case nameof(price):
case nameof(amount):
// Perform an internal calculation.
recalcTotal();
break;
default:
// Notify subscribers of important changes like product and total.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
break;
}
}
private void recalcTotal()
{
total = price * amount;
}
...
}
连接parent
class 中的total
属性。
现在唯一缺少的是有一种方法可以告诉parent_object
所有行都需要一个新的全局总计。 好消息是绑定已经在前面的步骤中就位。 要检测对childs
的任何更改,无论是添加新行还是编辑总计,请订阅子集合的ListChanged
事件,方法是将其设为OnLoad
中的第一行(在添加任何项目之前)。
childs.ListChanged += parent_object.onChildrenChanged;
这是需要在parent_object
class 中实现的方法。 像这样的东西:
internal void onChildrenChanged(object sender, ListChangedEventArgs e)
{
var tmpTotal = 0m;
foreach (var child in (IList<child>)sender)
{
tmpTotal += child.total;
}
total = tmpTotal;
}
准备测试
如果您实施这些步骤,您将拥有一个功能齐全的链接视图,您可以在其中添加、删除和修改child
记录。
希望这能提供一些关于所有拼图如何组合在一起的整体见解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.