编辑:我标记了一个答案,因为它确实让我走上了正确的轨道。剩下的唯一问题似乎是设计问题,根据董事会规则,应该作为一个单独的问题提出。在此处查看我的后续问题:https ://stackoverflow.com/questions/19744475/design-issue-how-to-approach-this-specific-task 感谢您的帮助!
我正在尝试将自定义对象列表绑定到 DataGrid。直接绑定似乎很容易,但我需要为一些额外的字段指定一些复杂的公式,这些额外的字段不会直接出现在我的课堂上。我还希望能够编辑网格中的数据并获取相关字段的更新。让我给你举个例子,因为它真的很难解释。我会将其简化为带有物品的房间。每个项目可以是红色和蓝色。
我的班级看起来像这样:
public class room
{
public string strRoomName { set; get; }
public string strItemname { set; get; }
public int intRedItem { set; get; }
public int intBlueItem { set; get; }
}
现在如果我使用 dataTable.ItemSource = myList; 我得到这样的东西:
nr. | room | name | red | blue
1. living room, ball, 2, 1
2. sleeping room, bunny, 4, 1
3. living room, chair, 3, 2
4. kitchen, ball, 4, 7
5. garage, chair, 1, 4
现在对于复杂的部分,我需要帮助。我希望每个项目都是相同的数字,红色和蓝色。因为这不成立,所以我想看到每个房间的“不平衡”,并且在全球范围内是这样的:
nr. | room | name | red | blue | missing | global red | global blue | global missing
1. living room, ball, 2, 1, 1 blue, 6, 7, 1 red
2. sleeping room, bunny, 4, 1, 3 blue, 4, 1, 3 blue
3. living room, chair, 3, 2, 1 blue, 4, 6, 2 red
4. kitchen, ball, 4, 7, 3 red, 6, 7, 1 red
5. garage, chair, 1, 4, 3 red, 4, 6, 2 red
正如您所看到的,这听起来像 excel 公式,但是我不确定如何在 c# 代码中处理这个问题。您还可以看到我需要在同一行中使用数据,但还需要从与一个属性(项目名称)匹配的其他行获取数据。
此外,如果我将第 1 行中的蓝色值 = 1 更改为值 = 2,我希望第 1 行读取如下:
1. living room, ball, 2, 2, even, 6, 8, 2 red
和 corse line 4 需要更改为:
4. kitchen, ball, 4, 7, 3 red, 6, 8, 2 red
编辑:在阅读了您的答案并测试了我实施您的提示的技能之后,我现在将以下代码作为我的课程:
public class RoomList : ObservableCollection<room>
{
public RoomList() : base()
{
Add(new room() { strRoomName = "living room", strItemname = "ball", intRedItem = 2, intBlueItem = 1 });
Add(new room() { strRoomName = "sleeping room", strItemname = "bunny", intRedItem = 4, intBlueItem = 1 });
Add(new room() { strRoomName = "living room", strItemname = "chair", intRedItem = 3, intBlueItem = 2 });
Add(new room() { strRoomName = "kitchen", strItemname = "ball", intRedItem = 4, intBlueItem = 7 });
Add(new room() { strRoomName = "garage", strItemname = "chair", intRedItem = 1, intBlueItem = 4 });
}
}
//rooms
public class room : INotifyPropertyChanged
{
public string strRoomName { set; get; }
public string strItemname { set; get; }
private int _intRed = 0;
private int _intBlue = 0;
public int intRedItem
{
get { return _intRed; }
set
{
_intRed = value;
NotifyPropertyChanged("intRedItem", "strMissing");
}
}
public int intBlueItem
{
get { return _intBlue; }
set
{
_intBlue = value;
NotifyPropertyChanged("intBlueItem", "strMissing");
}
}
public string strMissing
{
get
{
int missingCount = intRedItem - intBlueItem;
return missingCount == 0 ? "Even" : missingCount.ToString();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(params string[] propertyNames)
{
if (PropertyChanged != null)
{
foreach (string propertyName in propertyNames)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
编辑 1:我立即得到了“缺失”的字段,非常感谢这个提示。它真的和我想象的一样简单,并且对未来的项目很有用。
Edit2:通过在我的类中添加私有虚拟变量修复了 StackOverflow-Error,请参见上面的代码。
Edit3:也修复了资源,即使我发誓我昨天使用了完全相同的代码,但现在它正在工作。那好吧。
只剩下一个真正的问题:
如何根据其他对象属性设置属性。“globalRed”属性需要遍历我的列表或集合,但两者似乎都不是一个选项。至少不像我通常在代码中这样做。“listRooms”不会出现在属性 getter 中。在添加新对象后,这也需要再次循环。我想然后 otify 方法也会处理这个问题,但是我首先要如何循环呢?
还有一个问题可以更好地理解:
谁能用简单的话解释一下为什么上面的集合比列表方法更可取?尽管我能够测试它们的行为相同。
//the list-Way
datagridRooms.ItemsSource = listRooms.Where(x=>x.strRoomName == "living room");
//indentical with the collection-way...
datagridRooms.ItemsSource = new RoomList().Where(x=>x.strRoomName== "living room");