LINQ填充DataGrid后,无法提取SelectedItem数据填充TextBox问题
嘿,这个问题我熟!你遇到的InvalidCastException根本原因很明确——你填充DataGrid的是LINQ返回的匿名类型对象,而不是Cards实体类,所以强行转成bdCustomer.Cards肯定会失败。毕竟匿名类型是编译器自动生成的临时类型,和你定义的Cards完全是两回事。
下面给你三种可行的解决方法,按推荐程度排序:
1. 推荐:创建强类型DTO(数据传输对象)
这是最规范、最安全的做法,适合正式项目使用。
首先定义一个和你LINQ查询结果结构匹配的DTO类:
// 可以放在项目的Models或者Dtos文件夹下 public class CardCustomerInfo { public string Number { get; set; } // 属性名可自定义,也可和原表字段保持一致 public decimal Amount { get; set; } public int CustomerID { get; set; } }
然后修改你的LINQ查询,返回这个DTO的集合,而不是匿名类型:
// 假设db是你的数据库上下文实例 var query = from card in db.Cards join customer in db.Customers on card.CustomerID equals customer.CustomerID select new CardCustomerInfo { Number = card.Number, Amount = card.Ammount, CustomerID = card.CustomerID }; // 填充DataGrid dataGrid.ItemsSource = query.ToList();
最后在MouseDoubleClick事件里,就可以安全地强转SelectedItem了:
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var selectedInfo = dataGrid.SelectedItem as CardCustomerInfo; if (selectedInfo != null) { txtNumber.Text = selectedInfo.Number; txtAmount.Text = selectedInfo.Amount.ToString(); // 如果需要显示CustomerID也可以直接取 // txtCustomerID.Text = selectedInfo.CustomerID.ToString(); } }
这种方法的好处是编译时就有类型检查,不会因为属性名拼写错误导致运行时异常,后期维护也更方便。
2. 快速解决:使用dynamic类型
如果你只是想快速搞定,不想额外定义类,可以用C#的dynamic类型来绕过编译时类型检查:
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) { if (dataGrid.SelectedItem == null) return; dynamic selectedRow = dataGrid.SelectedItem; // 注意这里的属性名要和你LINQ匿名类型里的完全一致(包括大小写!) txtNumber.Text = selectedRow.number.ToString(); txtAmount.Text = selectedRow.ammount.ToString(); }
这种方法简单直接,但缺点是没有编译时检查——如果匿名类型的属性名拼写错了,只有运行时才会报错,适合临时测试或者小型项目使用。
3. 不推荐:用反射提取属性
如果上面两种方法都不适用,还可以通过反射来读取匿名类型的属性值,但这种方法代码繁琐,性能也差,一般不推荐:
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var selectedItem = dataGrid.SelectedItem; if (selectedItem == null) return; var itemType = selectedItem.GetType(); // 获取number属性值 var numberValue = itemType.GetProperty("number")?.GetValue(selectedItem)?.ToString(); // 获取ammount属性值 var amountValue = itemType.GetProperty("ammount")?.GetValue(selectedItem)?.ToString(); if (!string.IsNullOrEmpty(numberValue)) txtNumber.Text = numberValue; if (!string.IsNullOrEmpty(amountValue)) txtAmount.Text = amountValue; }
总结一下:优先用强类型DTO的方法,兼顾安全性和可维护性;快速测试用dynamic;反射尽量避免使用。
内容的提问来源于stack exchange,提问作者Dolander
相关产品推荐
相关产品推荐

