在WPF DataGrid中操作Content属性为何需强制类型转换?
WPF DataGrid 选中行赋值异常问题分析与解决
核心问题原因
当你直接写 lblID.Content = id.Content 时,本质是把 DataGridCell 里的TextBlock 控件本身转移到了 Label 的 Content 中。WPF 的 UI 元素只能属于一个父容器,控件被移走后,原来的 DataGridCell 就失去了内容,所以 ID 列会显示为空。当最后一行被选中后,后续操作会因为控件已被移除而触发 NullReferenceException。
而 ((TextBlock)id.Content).Text 是读取 TextBlock 的文本内容(字符串),只是把字符串值赋值给 Label,不会移动 UI 控件,因此不会出现内容消失或空引用的问题。
更优解决方案:放弃操作 UI 控件,直接绑定选中数据
你当前通过遍历 DataGrid 单元格控件获取数据的方式繁琐且易出错,WPF 的核心是数据绑定,直接操作选中的数据对象才是正确做法:
1. 重构 SelectionChanged 事件代码
替换原 dgPatientTable_SelectionChanged 方法:
private void dgPatientTable_SelectionChanged(object sender, SelectionChangedEventArgs e) { var selectedPatient = dgPatientTable.SelectedItem as dynamic; if (selectedPatient == null) { patientId = 0; // 清空编辑框 tbNameUpdate.Text = ""; tbPhoneUpdate.Text = ""; tbEmailUpdate.Text = ""; tbAddressUpdate.Text = ""; tbPostalzipUpdate.Text = ""; lblID.Content = ""; return; } // 直接访问数据对象属性,无需操作UI控件 lblID.Content = selectedPatient.ID.ToString(); patientId = selectedPatient.ID; tbNameUpdate.Text = selectedPatient.name; tbPhoneUpdate.Text = selectedPatient.phone; tbEmailUpdate.Text = selectedPatient.email; tbAddressUpdate.Text = selectedPatient.address; tbPostalzipUpdate.Text = selectedPatient.postalZip; }
2. 修复新增患者的上下文释放问题
原代码中 using (hp) 会释放类级别的 EF 上下文,导致后续查询报错,修改为:
private void btnAddPatient_Click(object sender, RoutedEventArgs e) { using (var hpContext = new hospitalEntities()) { patient newPatient = new patient() { name = tbName.Text, phone = tbPhone.Text, email = tbEmail.Text, address = tbAddress.Text, postalZip = tbPostalZip.Text }; hpContext.patients.Add(newPatient); hpContext.SaveChanges(); // 清空输入框 tbName.Clear(); tbPhone.Clear(); tbEmail.Clear(); tbAddress.Clear(); tbPostalZip.Clear(); InitializeTable(); } }
额外建议
- 避免使用匿名类型,建议创建
PatientViewModel类来封装查询结果,替换匿名类型,这样可以去掉dynamic,提升代码的类型安全性。 - WPF 中操作 UI 控件获取数据属于反模式,优先使用数据绑定(比如将编辑框直接绑定到选中的患者对象),能进一步减少代码量和异常风险。
内容的提问来源于stack exchange,提问作者Kadam
相关产品推荐
相关产品推荐

