Accessing of Rows in Silverlight DataGrid

本文介绍了一种在 Silverlight 中枚举 DataGrid 所有行的有效方法。通过提供一个扩展方法 GetRows 和一个自定义的枚举器 GridRowEnumerator,解决了因虚拟化导致的行对象重复的问题。

Imagine you want to enumerate (enlist) all rows (DataGridRow) of Silverlight Grid (DataGrid). By design this is not very simple tasks.
For example, you want to do something like this:

foreach (DataGridRow rowItem in grid.Rows)
{
. . .
}

This very important and very frequent requirement is just an issue. You will notice that this is almost impossible and will start to research in internet. Good luck. So, I decided to post the code of extension class which makes this possible:

foreach (DataGridRow rowItem in grid.GetRows())
{
. . .
}

Here is the whole code:

/// <summary>
/// Extends the DataGrid.
/// </summary>
public static class DataGridExtensions
{
/// <summary>
/// Gets the list of DataGridRow objects.
/// </summary>
/// <param name="grid">The grid wirhrows.</param>
/// <returns>List of rows of the grid.</returns>
public static ICollection<DataGridRow> GetRows(this DataGrid grid)
{
List<DataGridRow> rows = new List<DataGridRow>();

foreach (var rowItem in grid.ItemsSource)
{
// Ensures that all rows are loaded.
grid.ScrollIntoView(rowItem, grid.Columns.Last());

// Get the content of the cell.
FrameworkElement el = grid.Columns.Last().GetCellContent(rowItem);

// Retrieve the row which is parent of given element.
DataGridRow row = DataGridRow.GetRowContainingElement(el.Parent as FrameworkElement);

// Sometimes some rows for some reason can be null.
if (row != null)
rows.Add(row);
}

return rows;
}
}

The code above shows theoretically the idea of accessing of rows. Unfortunately this will work only if the whole grid result can be placed at the current view. While calling of ScrollIntoView() grid will reuse instances of created cells and rows and replace with new bounded data over and over again. The result of so called row virtualization will be replacing of rows in the list.
To workaround this, I implemented the right extension method

public static IEnumerator<DataGridRow> GetRowsEnumerator(this DataGrid grid)
{
return new GridRowEnumerator(grid);
}


And here is the implementation of enumerator:

public class GridRowEnumerator : IEnumerator<DataGridRow>
{
private DataGrid m_Grid;

private IEnumerator m_Enumerator;

public GridRowEnumerator(DataGrid grid)
{
m_Grid = grid;

m_Enumerator = m_Grid.ItemsSource.GetEnumerator();
}

#region IEnumerator<DataGridRow> Members

public DataGridRow Current
{
get
{
var rowItem = m_Enumerator.Current;

// Ensures that all rows are loaded.
m_Grid.ScrollIntoView(rowItem, m_Grid.Columns.Last());

// Get the content of the cell.
FrameworkElement el = m_Grid.Columns.Last().GetCellContent(rowItem);

// Retrieve the row which is parent of given element.
//DataGridRow row = DataGridRow.GetRowContainingElement(el);
DataGridRow row = DataGridRow.GetRowContainingElement(el.Parent as FrameworkElement);

return row;
}
}

#endregion

#region IDisposable Members

public void Dispose()
{

}

#endregion

#region IEnumerator Members

object IEnumerator.Current
{
get
{
return this.Current;
}
}

public bool MoveNext()
{
return m_Enumerator.MoveNext();
}

public void Reset()
{
m_Enumerator.Reset();
}

#endregion
}






This line I put here to measure how some interesting words can dramatically increase landing frequency of boring technical posts.

Bayern Inter Football Soccer champions league

Please forgive me for this :)


Posted May 02 2010, 12:30 AM by Damir Dobric
Filed under: Silverlight
<think>好的,我现在需要解决用户遇到的“error accessing non-existent property 'MongoError' in MongoDB context”问题。首先,我要理解这个错误的具体情况。用户在使用MongoDB时,尝试访问一个不存在的属性'MongoError',导致程序抛出错误。接下来,我需要分析可能的原因。 首先想到的是版本兼容性问题。可能用户升级了MongoDB的驱动版本,而新版本中MongoError已经被弃用或移除了。例如,在Node.js的MongoDB驱动中,旧版本可能直接通过require('mongodb').MongoError来引用错误类,而新版本可能将其整合到其他模块或改用了不同的命名方式,比如MongoServerError或其他子类。这时候,如果用户代码仍按旧方式引用,就会找不到该属性。 其次,导入方式是否正确也是一个关键点。用户可能在代码中错误地导入了mongodb模块,比如使用解构赋值时没有正确解构出MongoError,或者模块的导出结构发生了变化。例如,新版本可能将错误类放在某个子对象中,需要更具体的导入路径。 另外,依赖安装的问题也不容忽视。如果用户的项目中mongodb包未正确安装,或者安装了错误的版本,也会导致无法找到MongoError。这时候需要检查package.json中的版本号,并确认node_modules目录下是否存在对应的包。 接下来,我需要逐步验证这些可能性。首先检查用户的代码中是如何导入MongoError的。如果是通过const { MongoError } = require('mongodb');,那可能需要改为从核心模块导入,比如const { MongoServerError } = require('mongodb');。同时查看官方文档,确认当前版本中错误类的结构和命名是否有变化。 然后,查看用户使用的驱动版本。如果是4.x或更高版本,MongoDB驱动进行了重构,错误处理部分可能有所调整。例如,某些错误被细分到不同的子类中,而MongoError可能作为基类仍然存在,但具体的错误类型需要使用特定的子类。这时候,用户可能需要根据具体的错误类型来引用对应的类,或者检查错误对象的名称和结构。 此外,异常处理的方式是否正确也是一个方面。用户可能在捕获错误时,没有正确判断错误类型,而是直接访问MongoError属性,导致引用不存在。这时候需要建议用户使用instanceof检查错误对象的类型,或者查看错误对象的code属性来判断具体的错误代码。 最后,建议用户更新代码以适应新版本的驱动,或者回退到旧版本以确保兼容性。同时,确保依赖安装正确,清理node_modules后重新安装,避免缓存或安装不完整带来的问题。 总结下来,可能的解决步骤包括:检查导入语句是否正确,确认驱动版本和文档中的变化,调整错误处理逻辑,以及确保依赖安装正确。同时,提供具体的代码示例和版本信息会有助于更精准地解决问题。</think>关于访问不存在属性 `MongoError` 的问题,通常与 MongoDB 驱动版本或代码兼容性相关。以下是逐步分析与解决方法: --- ### **1. 原因分析** - **驱动版本升级**:MongoDB Node.js 驱动(如 `mongodb` 包)在 4.x 版本后调整了错误类的导出方式,弃用了直接通过 `require('mongodb').MongoError` 的引用方式[^1]。 - **模块路径变化**:部分错误类被移动到子模块(如 `MongoServerError` 属于核心错误类,需从 `mongodb` 直接导入)。 - **依赖未正确安装**:`mongodb` 包未安装或版本冲突。 --- ### **2. 解决方法** #### **步骤1:检查导入方式** - **旧版本代码(3.x及以下)**: ```javascript const { MongoError } = require('mongodb'); ``` - **新版本(4.x及以上)**: ```javascript const { MongoServerError } = require('mongodb'); // 或直接通过错误对象判断类型 if (error instanceof MongoServerError) { // 处理错误 } ``` #### **步骤2:调整错误处理逻辑** 若使用 `try...catch` 捕获 MongoDB 操作错误: ```javascript try { await collection.insertOne(data); } catch (error) { if (error instanceof MongoServerError) { // 替换旧版 MongoError console.log("MongoDB 错误:", error.message); } else { console.log("其他错误:", error); } } ``` #### **步骤3:验证驱动版本** - 检查 `package.json` 中 `mongodb` 的版本: ```json "dependencies": { "mongodb": "^4.4.1" // 4.x 版本需使用新语法 } ``` - 降级驱动(不推荐): ```bash npm install mongodb@3.7.3 ``` #### **步骤4:清理并重装依赖** 避免缓存或安装不完整: ```bash rm -rf node_modules package-lock.json npm install ``` --- ### **3. 示例代码(兼容新旧版本)** ```javascript const { MongoClient, MongoServerError } = require('mongodb'); async function connect() { const client = new MongoClient('mongodb://localhost:27017'); try { await client.connect(); const db = client.db('test'); const result = await db.collection('users').insertOne({ name: 'Alice' }); console.log("插入成功:", result.insertedId); } catch (error) { if (error instanceof MongoServerError) { console.log("MongoDB 错误:", error.message); // 例如唯一键冲突 } else { console.log("未知错误:", error); } } finally { await client.close(); } } connect(); ``` --- ### **相关问题** 1. 如何判断 MongoDB 中的唯一键冲突错误? 2. MongoDB 驱动从 3.x 升级到 4.x 有哪些重大变更? 3. 如何处理 MongoDB 连接超时错误? [^1]: MongoDB Node.js 驱动文档:[连接指南](https://www.mongodb.com/docs/drivers/node/current/quick-start/)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值