0

我在提供对特定数据库表的读取访问权限的自定义列表上使用 ListCollectionView。下面是自定义列表的定义。

class MaterialCollection : IList
{
    #region Fields
    private Object syncRoot;
    private SQLiteConnection connection;
    #endregion

    #region IList Interface
    public object this[int index]
    {
        get
        {
            using (SQLiteCommand command = connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM Materials LIMIT 1 OFFSET @Index";
                command.Parameters.AddWithValue("@Index", index);
                using (SQLiteDataReader reader = command.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        return GetMaterial(reader);
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
            }
        }

        set
        {
            throw new NotImplementedException();
        }
    }

    public int Count
    {
        get
        {
            using (SQLiteCommand command = connection.CreateCommand())
            {
                command.CommandText = "SELECT Count(*) FROM Materials";
                return Convert.ToInt32(command.ExecuteScalar());
            }
        }
    }

    public bool IsFixedSize
    {
        get
        {
            return false;
        }
    }

    public bool IsReadOnly
    {
        get
        {
            return true;
        }
    }

    public bool IsSynchronized
    {
        get
        {
            return true;
        }
    }

    public object SyncRoot
    {
        get
        {
            return this.syncRoot;
        }
    }

    public IEnumerator GetEnumerator()
    {
        return Enumerate().GetEnumerator();
    }
    #endregion

    #region Constructor
    public MaterialCollection(SQLiteConnection connection)
    {
        this.connection = connection;
        this.syncRoot = new Object();
    }
    #endregion

    #region Private Methods
    private Material GetMaterial(SQLiteDataReader reader)
    {
        int id = Convert.ToInt32(reader["Id"]);
        string materialNumber = Convert.ToString(reader["MaterialNumber"]);
        string type = Convert.ToString(reader["Type"]);
        string description = Convert.ToString(reader["Description"]);
        string alternateDescription = Convert.ToString(reader["AlternateDescription"]);
        string tags = Convert.ToString(reader["Tags"]);

        Material material = new Material();
        material.Id = id;
        material.MaterialNumber = materialNumber;
        material.Type = (MaterialType)Enum.Parse(typeof(MaterialType), type);
        material.Description = description;
        material.AlternateDescription = alternateDescription;
        material.Tags = tags;

        return material;
    }

    private IEnumerable<Material> Enumerate()
    {
        using (SQLiteCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT * FROM Materials";
            using (SQLiteDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    yield return GetMaterial(reader);
                }
            }
        }
    }
    #endregion

    #region Unimplemented Functions
    public int Add(object value)
    {
        throw new NotImplementedException();
    }

    public void Clear()
    {
        throw new NotImplementedException();
    }

    public bool Contains(object value)
    {
        throw new NotImplementedException();
    }

    public void CopyTo(Array array, int index)
    {
        throw new NotImplementedException();
    }

    public int IndexOf(object value)
    {
        return 0;
    }

    public void Insert(int index, object value)
    {
        throw new NotImplementedException();
    }

    public void Remove(object value)
    {
        throw new NotImplementedException();
    }

    public void RemoveAt(int index)
    {
        throw new NotImplementedException();
    }
    #endregion
}

问题是在DataGrid 的初始填充期间,对每一行(即0 到Count - 1)调用this[int index] 方法。

由于该表可能包含数百万行并且读取操作的成本很高(即传统 HDD 上的 SQLite),因此这样的操作是不可接受的。此外,当屏幕只能容纳 50 个左右的项目时,加载所有数百万行是没有意义的。

我想让 DataGrid 只获取它正在显示的行,而不是获取整个表。这样的工作怎么可能?

(PS 我已确保为 DataGrid 本身启用了虚拟化)

4

1 回答 1

1

将 ScrollViewer.CanContentScroll="True" 添加到 ListView 后,问题似乎得到了解决。

于 2015-12-17T11:58:02.657 回答