【问题标题】:DataGridCell and Custom Framework Element ContentDataGridCell 和自定义框架元素内容
【发布时间】:2012-10-01 14:03:28
【问题描述】:

我正在考虑将我的一个应用程序转换为 WPF,我主要关心的问题之一是 DataGrid 控件的性能(我用户的计算机是过时的 XP 计算机,没有专用图形)。我尝试了几千行,滚动性能很糟糕。

我想知道是否有办法将数据网格单元格的内容设置为派生自 FrameworkElement 的自定义类?

下面是一个示例类,它在放入虚拟化堆栈面板时似乎具有更好的性能:

public class LiteTextBlock : FrameworkElement
{
    private Size _mySize;
    private string _myText;
    private double totalWidth;
    private GlyphTypeface _typeface;
    private int _fontSize;
    private GlyphRun _run;

    public LiteTextBlock(Size mySize, string myText, GlyphTypeface typeface, int fontSize)
    {
        _mySize = mySize;
        this.Width = _mySize.Width;
        this.Height = _mySize.Height;
        _myText = myText + " additional information";
        _typeface = typeface;
        _fontSize = fontSize;
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        if (_run == null)
        {
            totalWidth = 0;

            ushort[] glyphIndexes = new ushort[_myText.Length];
            double[] advanceWidths = new double[_myText.Length];

            for (int i = 0; i < _myText.Length; i++)
            {
                ushort glyphIndex = _typeface.CharacterToGlyphMap[_myText[i]];
                double width = _typeface.AdvanceWidths[glyphIndex] * _fontSize;

                if (totalWidth + width >= _mySize.Width - 10)
                {
                    Array.Resize(ref glyphIndexes, i);
                    Array.Resize(ref advanceWidths, i);
                    break;
                }

                glyphIndexes[i] = glyphIndex;
                advanceWidths[i] = width;
                totalWidth += width;
            }

            Point origin = new Point(5, 0);

            _run = new GlyphRun(_typeface, 0, false, _fontSize, glyphIndexes
                , origin, advanceWidths, null, null, null, null, null, null);
        }

        drawingContext.DrawGlyphRun(Brushes.Black, _run);
    }
}

谁能告诉我这是否可行?

免责声明:我已经尝试过使用轻量级控件,例如 ListView,但性能仍然很差。

【问题讨论】:

  • 您能否发布导致性能不佳的代码/XAML?

标签: c# wpf datagrid


【解决方案1】:

是的,有办法。

您需要实现您的自定义DataGridColumn 并覆盖其GenerateElement 方法,并且您需要处理DataGrid.AutoGeneratingColumn 事件以将您的自定义DataGridColumn 设置为DataGrid。

这是自定义 DataGridColumn 的示例:

public class DataGridLiteTextColumn : DataGridColumn
{
    private readonly PropertyDescriptor property;

    private readonly GlyphTypeface glyphTypeface = new GlyphTypeface(new Uri("file:///C:\\WINDOWS\\Fonts\\Arial.ttf"));

    public DataGridLiteTextColumn(PropertyDescriptor property)
    {
        this.property = property;
    }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var value = property.GetValue(dataItem);
        return new LiteTextBlock(new Size(100, 20), value != null ? value.ToString() : string.Empty, this.glyphTypeface, 10);
    }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        throw new NotImplementedException();
    }
}

这是 DataGrid.AutoGeneratingColumn 事件的处理程序:

private void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    e.Column = new DataGridLiteTextColumn((PropertyDescriptor)e.PropertyDescriptor);
}

此代码将用于显示值,尽管 LiteTextBlock 构造函数大小参数可能未设置为适当的值。要编辑值,您还必须实现GenerateEditingElement 方法。

【讨论】:

    【解决方案2】:

    确保 DataGrid 的 EnableRowVirtualization 属性设置为 True。默认情况下它应该是 True,但请确保它没有在某处的 Style 中设置为 False。

    【讨论】:

      【解决方案3】:

      UI Virtualization 默认启用。但它会在以下任一情况下被禁用 -

      1. 在测量排列过程中,DataGrid 的高度不受限制。 如果 DataGrid 认为它有足够的空间来排列所有项目,那么它不会虚拟化任何东西。 这通常发生在您将 DataGrid 放在堆栈面板中时。

      2. 数据网格的 ItemsPanel。 虚拟化由 VirtualizingStackPanel 完成。如果您更改 ItemsPanel,VirtualizingStackPanel 将被移除。

      3. 项目分组。 在 .NET4.0 中,虚拟化不支持分组。在某些情况下,将 GroupStyle 分配给 DataGrid 将关闭虚拟化,即使项目未分组。

      请检查您没有陷入上述任何情况。

      附带说明,您还可以在数据网格的项目源上实现Data Virtualization。可以在此处找到具有相同证明的示例 - Data Virtualization

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-18
        • 1970-01-01
        • 1970-01-01
        • 2020-05-22
        • 1970-01-01
        相关资源
        最近更新 更多