C# 响应类对象层次结构中的对象属性更改
我正在开发一个应用程序,它使用分层对象结构,并在DataGridView的主GUI上显示这些对象的一些关键对象属性。这些值必须在基础数据更改时更新。我考虑过几个选择:C# 响应类对象层次结构中的对象属性更改,c#,oop,events,C#,Oop,Events,我正在开发一个应用程序,它使用分层对象结构,并在DataGridView的主GUI上显示这些对象的一些关键对象属性。这些值必须在基础数据更改时更新。我考虑过几个选择: 将各个DataGridView单元格绑定到相关的对象属性。我知道这是不可能的,DGV绑定要么全有要么全无 动态地将文本框放置在网格单元上并绑定它们,但这看起来很混乱 创建一个只引用相关对象属性的中间列表/数组/集合,然后将该列表用作DataGridView的数据源 响应PropertyChanged事件。复杂的是我上了多节课。顶层
project.PropertyChanged += new PropertyChangedEventHandler(ProjectPropertyChanged);
private void ProjectPropertyChanged(object sender, PropertyChangedEventArgs e) {
MessageBox.Show("In main UI. Project property changed!");
}
再往下一层,我得到了这样的东西:
public class Project : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Project() {
childObject.PropertyChanged += new PropertyChangedEventHandler(ProjectPropertyChanged);
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
ProjectPropertyChanged(sender, e); // this doesn't work due to different parameters
}
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Event available to parent class
}
}
其思想是,每个类都将自己的OnPropertyChanged()事件传递给其PropertyChanged()方法,并响应其子类的OnPropertyChanged()事件,并将所有事件公开给父类
如果这样做,理想情况下,我希望保留哪些属性发生了变化的知识,以便做出相应的响应
最直接的问题是由于参数不同,ProjectPropertyChanged和OnPropertyChanged之间缺乏兼容性。但更根本的是,我不确定这种方法是可行的还是最佳的
如何最好地做到这一点?回答我自己的问题: 我尝试使用一个中间绑定源,使用一个DataTable(如所示),但没有成功。问题是我无法创建对数据对象的引用。DataTable似乎包含值 所以我最终使用了一种我更确定但不那么优雅的方法,这就是我上面问题中的选项2。我将标签放置在需要绑定数据值的位置,并绑定到这些标签。这很有效 经过一些简化,并假设我们的物体是动物,我的解决方案是:
Label[,] dashboardLabels = new Label[3,14];
private void Form1_Shown(object sender, EventArgs e)
{
CreateLabels(); // create and position labels (no binding yet)
}
public void CreateLabels(int cols = 3, int rows = 14)
{
for (int col = 0; col < cols; col++)
{
for (int row = 0; row < rows; row++)
{
// Create label...
Label l = new Label();
l.Text = "N/A";
l.ForeColor = Color.Red
dashboardLabels[col, row] = l;
this.Controls.Add(l);
// Position label over DGV cell...
Point dgvCell = dataGridView1.GetCellDisplayRectangle(col + 2, rowNumbersLabel[row], false).Location;
Point dgvGrid = dataGridView1.Location;
l.Left = dgvGrid.X + dgvCell.X;
l.Top = dgvGrid.Y + dgvCell.Y;
}
}
}
private void UpdateLabels(List<Dog> dogs)
{
for (int i = 0; i < dogs; i++)
{
if (!dashboardLabels[i, 0].Visible) dashboardLabels[i, 0].Visible = true;
if (dogs[i].IsSetUp) BindLabel(dashboardLabels[i, 0], dogs[i],"Name");
}
}
private void BindLabel(Label l, Dog dog, string observation)
{
Binding b = new Binding("Text", dog, observation);
l.DataBindings.Add(b);
l.ForeColor = Color.Green;
}
}
Label[,]仪表板标签=新标签[3,14];
显示私有void Form1_(对象发送方,事件参数e)
{
CreateLabels();//创建和定位标签(尚未绑定)
}
公共void CreateLabels(int cols=3,int rows=14)
{
for(int col=0;col
然后在创建对象时,我调用UpdateLabels()
。如果未初始化,此时标签将以红色显示“不适用”。如果初始化,标签将变为绿色,并将绑定到对象的名称,以便从该点起自动更新
我做了很多搜索,发现的信息表明DataGridView不支持复杂的数据绑定,即它几乎是一个类到一个DGV,或者根本不支持。我找不到替代的类似网格的控件来执行此操作。子对象是否修改主对象的属性?--DataGridView不能显示嵌套的对象值,所有对象都必须位于同一层次结构级别。将对象绑定到BindingSource(此类处理属性更改通知)并将DGV绑定到BindingSource。或者使用DataTable来表示数据:此类本身会引发通知更改(您可以将DataTable绑定到BindingSource以获得更多导航选项)。正如我所说的,我不认为数据绑定到DGV是显而易见的解决方案,因为其中的属性属于多个对象。您是否建议我使用包含不同对象属性的中间列表并将其用作数据源?DGV中的数据只能以列和行的形式显示,因此没有嵌套对象,您必须展平层次结构。你计划怎么做,你想在DGV中展示什么,你没有说。无论如何都需要一个表示层。如果表示层引发通知更改,UI要求得到满足,BindingSource可以处理类对象和UI(在本例中是DGV,但处理数据绑定的任何其他控件)之间的事务