向DataGrid中的特定列添加数据
向DataGrid中的特定列添加数据
我想在按钮点击事件中创建一个新列,并且仅向该新列添加值。是否可行?该列可能会有一些行,具体取决于报价中的项目数量。
我目前已经实现的部分:
存储所有信息的类:
public class ViewQuoteItemList { ... public double SupplierCost { get; set; } ... }
我可以创建列并将其绑定到我的`ViewQuoteItemList`类:
DataGridTextColumn columnFeedbackSupplier = new DataGridTextColumn(); columnFeedbackSupplier.Binding = new Binding("SupplierCost"); // 列的标题从下拉列表框中选择添加到数据网格的公司名称中获取 columnFeedbackSupplier.Header = (cmbFeedbackSelectSupplier.SelectedItem as DisplayItems).Name;
然后,我从不同的数据网格获取我的报价项目,并将它们添加到我想要添加新列及其值的第二个数据网格中:
IList list = dgFeedbackAddCost.SelectedItems as IList; IEnumerableitems = list.Cast (); var collection = (from i in items let a = new ViewQuoteItemList { SupplierCost = 0 } select a).ToList();
最后,我将新列添加到第二个数据网格,并将`collection`设置为数据网格的`ItemSource`:
dgFeedbackSelectSupplier.Columns.Add(columnFeedbackSupplier); dgFeedbackSelectSupplier.ItemsSource = collection;
我的问题是,一旦我编辑了一个供应商的单元格数据,整行的所有单元格都会更新为相同的值,因为它们都绑定到同一个类/项目源。这个问题可以修复吗?
编辑:
“整行的所有单元格都会更新”意味着每次我在一行的一个单元格中插入一个值时,该行的每个单元格都会更新为相同的值。下面是一些图片展示我所说的。我想编辑所有的数据,这些都发生在我的第二个数据网格(dgFeedbackSupplier)上。
这里,我添加了两个公司和我想要比较价格的4个项目。现在,我想点击公司下面的单元格并为特定项目添加一个值。
[图片链接](https://i.stack.imgur.com/71PSk.jpg)
我双击一个单元格来编辑/更改值。
[图片链接](https://i.stack.imgur.com/Xcpbf.jpg)
然后,当我在选择的单元格中更改值时,同一行中其他公司的该特定项目的值也会更新为相同的值。
[图片链接](https://i.stack.imgur.com/odmqY.jpg)
这就是我的问题,我需要仅更改那个单元格的值,而不是整行。
编辑2:
如何将`collection`转换为`ExpandoObject`?
var collection = (from i in items let a = new ViewQuoteItemList { Item = i.Item, Supplier = 25 } select a).ToList();
编辑3:
我的XAML:
这是我的整个方法的代码,其中添加了列并从其他数据网格获取项目:
private void btnFeedbackSelectSupplier_Click(object sender, RoutedEventArgs e) { supplier.Id = (cmbFeedbackSelectSupplier.SelectedItem as DisplayItems).Id;// 暂时未使用 supplier.Name = (cmbFeedbackSelectSupplier.SelectedItem as DisplayItems).Name; DataGridTextColumn columnFeedbackSupplier = new DataGridTextColumn(); columnFeedbackSupplier.Binding = new Binding("Supplier") { Mode = BindingMode.TwoWay }; columnFeedbackSupplier.CanUserReorder = true; columnFeedbackSupplier.CanUserResize = true; columnFeedbackSupplier.IsReadOnly = false; columnFeedbackSupplier.Header = supplier.Name; dgFeedbackAddCost.SelectAll(); IList list = dgFeedbackAddCost.SelectedItems as IList; IEnumerableitems = list.Cast (); var collection = new List (); foreach (var i in items) { dynamic a = new ExpandoObject(); a.Id = (cmbFeedbackSelectSupplier.SelectedItem as DisplayItems).Id; a.Item = i.Item; a.Supplier = 25; collection.Add(a); } dgFeedbackSelectSupplier.Columns.Add(columnFeedbackSupplier); dgFeedbackSelectSupplier.ItemsSource = collection; }
问题的出现原因:
这个问题的出现是因为用户想要在一个DataGrid中的特定列中添加数据,但是不知道如何实现。
解决方法:
解决方法是使用Microsoft Dynamics的ExpandoObject。用户需要创建一个List
用户可以使用Expando的简单方法进行操作,例如:
var dynamicItem = New ExpandoObject();
dynamicItem.Item = "Test";
dynamicItem.BarlwoodCityDeep = (int)350;
用户也可以将dynamicItem视为字典进行操作,例如:
IDictionary
dynamicDict.Add("MyNewProperty","MySomeValue")
建议用户编写一个将dataList映射到新expandoList并将其绑定到视图的方法,并确保在WPF中使用自动生成列,以便新添加的列可见。
用户还可以查看类似情况下为我工作的解决方案。
如果用户对dynamics不熟悉,可能会觉得有点棘手,但是使用Expandos真的很酷,使用它们非常方便。
将ViewQuoteItemList转换为Expando的代码示例:
var collection = new List
foreach (var i in items)
{
dynamic a = new ExpandoObject();
a.Item = i.item;
a.Supplier = 25;
collection.Add(a);
}
相关文章:
用户可以在这里找到相关文章。
感谢提供答案!一旦我把所有的东西都搞定了,我会立即告诉你的。
ExpandoObjects真的很酷(或者我到目前为止学到的东西),但是我遇到的一个问题是:“All the properties in ViewQuoteItem are added to this new Object”。我如何将我的ViewQuoteItemList设置为ExpandoObject?
我已经添加了一个简化的代码来将您的对象转换为Expando。
非常感谢您迄今为止提供的所有帮助。不过我还有几个问题。对此我感到抱歉,但是看起来您的编码确实引导我朝着正确的方向前进。我的新列已经正确添加,我可以看到每个公司下的项目的显示值为25。我目前的主要问题是,这些值仍然与网格中的每个公司相连,当我更改一个值时,选定行中的所有值都会更改。所以我的问题是,您能否展示给我如何将每个添加的列分开,使其拥有自己的值?
对于给您带来的不便和我的回复速度慢,我感到很抱歉,但是我需要这么长时间来弄清楚一切,因为我对C#编程还非常陌生,对于您在答案中试图向我解释的内容我并不完全理解。
我已经添加了我的XAML,并插入了整个方法,所有事情都应该在那里发生。
您需要在XAML中将集合绑定到网格,请阅读有关数据网格绑定的内容,然后处理ColumnAutoGeneratingEvent并在其中添加列。
问题的原因是无法使用集合来绑定第二个DataGrid,因为视图是动态的,可能具有可变的列数。解决方法是使用DataTable作为DataGrid的数据源。不要在DataGrid中添加列,而是在DataTable中添加列,并在Grid中自动生成列。
一个将数据源(任何类型)转换为DataTable的方法是:
public static DataTable DataGridtoDataTable(DataGrid dg) { dg.SelectAllCells(); dg.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader; ApplicationCommands.Copy.Execute(null, dg); dg.UnselectAllCells(); String result = (string)Clipboard.GetData(DataFormats.CommaSeparatedValue); string[] Lines = result.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); string[] Fields; Fields = Lines[0].Split(new char[] { ',' }); int Cols = Fields.GetLength(0); DataTable dt = new DataTable(); for (int i = 0; i < Cols; i++) dt.Columns.Add(Fields[i].ToUpper(), typeof(string)); DataRow Row; for (int i = 1; i < Lines.GetLength(0) - 1; i++) { Fields = Lines[i].Split(new char[] { ',' }); Row = dt.NewRow(); for (int f = 0; f < Cols; f++) { Row[f] = Fields[f]; } dt.Rows.Add(Row); } return dt; }
然后,在需要在DataGrid中添加列的时候,通过迭代集合在表中添加列来填充数据表中的列。
这个问题没有简单的解决方法,因为你的场景是独特的,只有动态结构才能满足你的需求。使用DataTable,每个单元格都将绑定到唯一的实体。更改DataGrid单元格时,只有一个单元格会被更新(与集合不同,多个单元格绑定到同一个属性)。
在操作期间,全局剪贴板数据会被修改,最好在操作之前弹出当前剪贴板数据,并在操作后将其推回剪贴板。
感谢你的答案!我一有进展就会向你更新。
问题的出现的原因:
问题出现的原因是在尝试使用一个表格视图组件来显示非表格数据。实际上,所拥有的数据是层次结构的数据,而不是表格形式的数据。
解决方法:
解决方法是创建一个新的视图,将层次结构的数据填充并转换为表格形式。为了在XAML中能够选择适当的数据模板,可以使用虚拟类来填充空槽。解决方法遵循MVVM+XAML的方式,避免使用任何自定义代码,并将所有内容保持在MVVM+XAML方式中。通过使用MVVMLight中的messenger类来更新新视图,手动调用RaisePropertyChanged事件。在XAML中使用ItemsControl和UniformGrid组件创建表格视图。完整的解决方案可以在GitHub上找到。
文章如下:
从我理解的情况来看,你有供应商,这些供应商有商品。你可以添加新的供应商。我假设供应商可能没有所有的商品(为了增加挑战性 :))。
你想以表格视图的方式呈现这个数据结构。
问题在于你试图使用一个表格视图组件来显示非表格形式的数据。实际上,你拥有的是一个层次结构的数据。在继续解决方案之前,这里有一些屏幕截图。
(插入图片)
基本上,我在这里创建了基于层次结构数据的新视图,填充了空槽,并将其转换为表格形式。我使用虚拟类来填充空槽,这样我就可以在XAML中轻松选择适当的数据模板。我避免使用任何自定义代码,将所有内容都保持在MVVM+XAML方式中。因此,绑定等都按预期工作。
当集合发生变化时,必须更新新的视图,所以我使用了MVVMLight中的messenger类来实现简便,并手动调用RaisePropertyChanged事件。
在XAML中,我使用ItemsControl和UniformGrid组件创建了表格视图。
我在GitHub上放置了完整的解决方案。
如果出现构建错误,请右键单击解决方案并还原NuGet包。
非常感谢你的回答。然而,有点晚了。我已经找到了在我的数据表格中如何做到这一点的方法。我将在今天晚些时候发布答案,如果有机会的话!再次感谢你的努力。
没问题,这是一个有趣的问题。我觉得以后可能会用到。
太好了,我发布了一个答案,展示了我的代码以及我是如何解决这个谜题的。希望它能在将来对你有所帮助。