DataGrid更新XML属性时批量赋值异常的排查与修复请求
问题描述
通过GetProductsPriceList()方法从XML文件读取指定节点属性并加载到DataGrid,编辑Visible和Price列后保存回XML时,所有产品的这两个属性被设置为同一个值。调试时pp.Visible和pp.Price的内容正确,但循环写法有误,需要修复以实现每个产品对应更新XML中属性。
读取数据的代码:
private ObservableCollection<Products> GetProductsPriceList() { productpricelist = new ObservableCollection<Products>(); XmlDocument doc = new XmlDocument(); doc.Load(@"C:\xmltest\26112023.txt"); foreach (XmlElement pn in doc.SelectNodes("/Data/Products/*")) { var productlist = new Products { Mainproduct = pn.LocalName.ToString(), Name = pn.GetAttribute("Name"), Price = pn.SelectSingleNode(".//ProductPrice/@Price")?.Value, Visible = pn.SelectSingleNode(".//ProductVisibility/@Visible")?.Value, NameIcon = pn.GetAttribute("DefaultIconName") }; productpricelist.Add(productlist); } return productpricelist; }
原始保存代码:
private void Execute(object parm) //method to save back to the xml file price & visible attributes for each products { XmlDocument doc = new XmlDocument(); doc.Load(@"C:\xmltest\26112023.txt"); foreach (Products pp in productpricelist) { foreach (XmlElement pn in doc.SelectNodes("/Data/Products/*")) { foreach (XmlNode visibility in pn.SelectNodes("Visibilities")) { foreach (XmlNode productVisibilty in visibility.SelectNodes("ProductVisibility")) { productVisibilty.Attributes["Visible"].InnerText = pp.Visible; foreach (XmlNode price in productVisibilty.SelectNodes("Prices")) { foreach (XmlNode productPrice in price.SelectNodes("ProductPrice")) { productPrice.Attributes["Price"].InnerText = pp.Price; } } } } } } doc.Save(@"C:\xmltest\26112023_.txt"); }
XML示例片段:
<?xml version="1.0" encoding="utf-8"?> <Data> <ShippingMethodsReferences /> <Products> <ProductApple ID="77f9df03-7525-44d7-b08d-dcf106b44969" Sys_Type="Library.Domain.Products.ProductApple" Sys_ImportStrategy="UpdateOnly" DefaultIconName="Xerox_10x8x2_R_Sticker.png" Profile="Fruits" DefaultOutputProfileTypeFullName="Output" Name="(10x8)x2 H Rectangular"> <ShippingMethodPrices ImportStrategy="Replace" /> <Visibilities ImportStrategy="Replace"> <ProductVisibility ID="adfa5eca-3f58-4107-8738-5b9b1c0b666f" Visible="True"> <Prices ImportStrategy="Replace"> <ProductPrice ID="e558ceed-1e64-4540-8958-0203fea2b53b" Price="0" /> </Prices> </ProductVisibility> </Visibilities> </ProductApple> <ProductSolo ID="7c1302d8-8832-451b-be64-c5d048d0332f" Name="(10x8)x2 H Rectangular"> <Visibilities ImportStrategy="Replace"> <ProductVisibility ID="078f6e6a-895c-4957-b808-2b38589ba4cd" Visible="True"> <Prices ImportStrategy="Replace"> <ProductPrice ID="0c14f953-9f75-4e24-9c38-245027107167" Price="0" /> </Prices> </ProductVisibility> </Visibilities> </ProductSolo> </Products> </Data>
问题原因
原始保存代码中,外层遍历每个Products对象时,内层又遍历XML中所有产品节点,导致每次循环都会把所有XML产品的Visible和Price属性替换为当前pp的值。最终所有产品的属性会被最后一个pp的值覆盖。
修复后的代码
核心思路:为每个Products对象找到XML中对应的产品节点(通过Mainproduct属性匹配节点名称),仅更新该节点下的属性:
private void Execute(object parm) { XmlDocument doc = new XmlDocument(); doc.Load(@"C:\xmltest\26112023.txt"); foreach (Products pp in productpricelist) { // 找到当前产品对应的XML节点(通过节点名称匹配Mainproduct) XmlElement productNode = doc.SelectSingleNode($"/Data/Products/{pp.Mainproduct}") as XmlElement; if (productNode == null) continue; // 如果找不到对应节点,跳过 // 更新Visible属性 XmlNode visibilityNode = productNode.SelectSingleNode(".//ProductVisibility"); if (visibilityNode != null && visibilityNode.Attributes["Visible"] != null) { visibilityNode.Attributes["Visible"].InnerText = pp.Visible; } // 更新Price属性 XmlNode priceNode = productNode.SelectSingleNode(".//ProductPrice"); if (priceNode != null && priceNode.Attributes["Price"] != null) { priceNode.Attributes["Price"].InnerText = pp.Price; } } doc.Save(@"C:\xmltest\26112023_.txt"); }
说明
- 使用
SelectSingleNode结合pp.Mainproduct直接定位到对应产品节点,避免遍历所有节点 - 增加空值判断,防止节点或属性不存在时引发异常
- 简化嵌套循环,提升代码可读性和执行效率
内容的提问来源于stack exchange,提问作者user838691
相关产品推荐
相关产品推荐

