You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF快速生成1000×1000矩形阵列及交互优化咨询

WPF 1000×1000矩形阵列高效实现方案

针对你的需求,直接创建大量UI元素或用普通Bitmap缩放的方法都会带来性能瓶颈,以下是两种能满足<0.1秒生成速度的最优方案:

一、自定义绘制控件(推荐,兼顾交互与性能)

通过继承FrameworkElement自定义控件,直接在OnRender中批量绘制矩形,结合鼠标事件实现索引定位与颜色修改。此方案利用WPF硬件加速,初始化和重绘效率极高。

代码实现

public class GridCanvas : FrameworkElement
{
    private const int GridSize = 1000;
    private Color[,] _gridColors;
    private double _cellWidth;
    private double _cellHeight;

    public GridCanvas()
    {
        // 批量初始化颜色数组,O(n)操作耗时可忽略
        _gridColors = new Color[GridSize, GridSize];
        for (int y = 0; y < GridSize; y++)
        {
            for (int x = 0; x < GridSize; x++)
            {
                _gridColors[x, y] = Colors.LightGray;
            }
        }

        // 绑定交互事件
        MouseMove += OnMouseMove;
        MouseLeftButtonDown += OnMouseLeftButtonDown;
    }

    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);
        _cellWidth = ActualWidth / GridSize;
        _cellHeight = ActualHeight / GridSize;

        // 按行批量绘制,减少DrawingContext调用次数
        for (int y = 0; y < GridSize; y++)
        {
            double top = y * _cellHeight;
            for (int x = 0; x < GridSize; x++)
            {
                var cellRect = new Rect(x * _cellWidth, top, _cellWidth, _cellHeight);
                dc.DrawRectangle(new SolidColorBrush(_gridColors[x, y]), null, cellRect);
            }
        }
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        var mousePos = e.GetPosition(this);
        int x = (int)(mousePos.X / _cellWidth);
        int y = (int)(mousePos.Y / _cellHeight);
        if (x is >= 0 and < GridSize && y is >=0 and < GridSize)
        {
            ToolTip = $"索引:({x}, {y})";
        }
    }

    private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var mousePos = e.GetPosition(this);
        int x = (int)(mousePos.X / _cellWidth);
        int y = (int)(mousePos.Y / _cellHeight);
        if (x is >=0 and < GridSize && y is >=0 and < GridSize)
        {
            // 切换单元格颜色
            _gridColors[x, y] = _gridColors[x, y] == Colors.LightGray ? Colors.Red : Colors.LightGray;
            // 局部重绘,仅更新修改的单元格
            var dirtyRect = new Rect(x * _cellWidth, y * _cellHeight, _cellWidth, _cellHeight);
            InvalidateVisual(dirtyRect);
        }
    }
}

优势

  • 初始化仅需初始化数组和绑定事件,耗时远小于0.1秒
  • 绘制基于WPF硬件加速,无大量UI元素的内存开销
  • 颜色修改时仅重绘单个单元格,响应延迟可忽略

二、WriteableBitmap像素级操作(适合需导出图片的场景)

如果需要将阵列导出为图片,或更底层的像素控制,使用WriteableBitmap直接操作内存缓冲区,比普通Bitmap快数倍。

代码实现

public class BitmapGridControl : UserControl
{
    private const int GridSize = 1000;
    private WriteableBitmap _wb;
    private int _pixelPerCell = 1; // 每个单元格占的像素数
    private byte[] _pixelBuffer;

    public BitmapGridControl(int pixelPerCell = 1)
    {
        _pixelPerCell = pixelPerCell;
        int totalWidth = GridSize * _pixelPerCell;
        int totalHeight = GridSize * _pixelPerCell;

        // 初始化WriteableBitmap
        _wb = new WriteableBitmap(totalWidth, totalHeight, 96, 96, PixelFormats.Bgr32, null);
        _pixelBuffer = new byte[totalWidth * totalHeight * 4]; // Bgr32格式每个像素4字节

        // 批量填充默认颜色(浅灰色)
        for (int i = 0; i < _pixelBuffer.Length; i += 4)
        {
            _pixelBuffer[i] = 0xD3;    // B
            _pixelBuffer[i + 1] = 0xD3;// G
            _pixelBuffer[i + 2] = 0xD3;// R
            _pixelBuffer[i + 3] = 0xFF;// A
        }

        UpdateBitmap();

        // 创建显示控件并绑定事件
        var displayImage = new Image { Source = _wb };
        displayImage.MouseMove += OnMouseMove;
        displayImage.MouseLeftButtonDown += OnMouseLeftButtonDown;
        Content = displayImage;
    }

    private void UpdateBitmap()
    {
        _wb.Lock();
        Marshal.Copy(_pixelBuffer, 0, _wb.BackBuffer, _pixelBuffer.Length);
        _wb.AddDirtyRect(new Int32Rect(0, 0, _wb.PixelWidth, _wb.PixelHeight));
        _wb.Unlock();
    }

    private void UpdateCellColor(int x, int y, Color targetColor)
    {
        int startX = x * _pixelPerCell;
        int startY = y * _pixelPerCell;

        // 批量修改单元格对应像素区域
        for (int dy = 0; dy < _pixelPerCell; dy++)
        {
            int rowStartIndex = (startY + dy) * _wb.PixelWidth * 4;
            for (int dx = 0; dx < _pixelPerCell; dx++)
            {
                int pixelIndex = rowStartIndex + (startX + dx) * 4;
                _pixelBuffer[pixelIndex] = targetColor.B;
                _pixelBuffer[pixelIndex + 1] = targetColor.G;
                _pixelBuffer[pixelIndex + 2] = targetColor.R;
                _pixelBuffer[pixelIndex + 3] = targetColor.A;
            }
        }

        // 局部更新Bitmap
        _wb.Lock();
        int bufferOffset = startY * _wb.PixelWidth * 4;
        int copyLength = _pixelPerCell * _pixelPerCell * 4;
        Marshal.Copy(_pixelBuffer, bufferOffset, _wb.BackBuffer + bufferOffset, copyLength);
        _wb.AddDirtyRect(new Int32Rect(startX, startY, _pixelPerCell, _pixelPerCell));
        _wb.Unlock();
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        var mousePos = e.GetPosition((UIElement)sender);
        int x = (int)(mousePos.X / _pixelPerCell);
        int y = (int)(mousePos.Y / _pixelPerCell);
        if (x is >=0 and < GridSize && y is >=0 and < GridSize)
        {
            ((UIElement)sender).ToolTip = $"索引:({x}, {y})";
        }
    }

    private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var mousePos = e.GetPosition((UIElement)sender);
        int x = (int)(mousePos.X / _pixelPerCell);
        int y = (int)(mousePos.Y / _pixelPerCell);
        if (x is >=0 and < GridSize && y is >=0 and < GridSize)
        {
            Color currentColor = GetCellColor(x, y);
            Color newColor = currentColor == Colors.LightGray ? Colors.Red : Colors.LightGray;
            UpdateCellColor(x, y, newColor);
        }
    }

    private Color GetCellColor(int x, int y)
    {
        int pixelIndex = (y * _pixelPerCell * _wb.PixelWidth + x * _pixelPerCell) * 4;
        return Color.FromArgb(
            _pixelBuffer[pixelIndex + 3],
            _pixelBuffer[pixelIndex + 2],
            _pixelBuffer[pixelIndex + 1],
            _pixelBuffer[pixelIndex]
        );
    }
}

优势

  • 直接操作内存缓冲区,初始化速度极快
  • 支持像素级控制,方便导出高清图片
  • 修改时仅更新目标单元格的像素区域,性能损耗极低

需避免的坑

  1. 不要创建1000×1000个Rectangle元素:单个UI元素的初始化和布局开销极大,1e6个元素会导致程序卡顿甚至崩溃
  2. 不要用普通Bitmap再缩放:普通Bitmap的像素操作无硬件加速,缩放过程会额外增加耗时
  3. 避免全局重绘:修改颜色时优先使用局部重绘,减少不必要的渲染开销

内容的提问来源于stack exchange,提问作者TheMelon2012

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:54:19