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

WPF DataGrid2D绑定后Canvas绘图变慢及内存泄漏问题解决

问题:切换矩阵项后Canvas绘图卡顿、内存飙升的解决办法

我开发的程序包含图形项和矩阵项:

  • 图形项:用于绘制椭圆和线条的Canvas
  • 矩阵项:使用DataGrid2DLibrary(命名空间xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary")将二维矩阵绑定至DataGrid2D

程序启动后操作图形时Canvas绘图流畅,但点击矩阵项让ItemsSource生效后,切回图形项时Canvas绘图变得缓慢,内存占用大幅增加。

我尝试过以下代码清空ItemsSource并清理内存,但效果不佳:

尝试的代码

MainWindow.xaml.cs

private void MatrixData(object sender, RoutedEventArgs e)
{
    if (MatrixMenu.IsChecked)
    {
        if (DrawingCanvas_Undirected.Visibility == Visibility.Visible || DrawingCanvas_Directed.Visibility == Visibility.Visible)
        {
            GraphItem.Visibility = Visibility.Visible;
        }

        MatrixItem.Visibility = Visibility.Collapsed;

        MatrixAdj.ItemsSource2D = null;
        MatrixInc.ItemsSource2D = null;
        MatrixMenu.IsChecked = false;
        GC.Collect();
    }
}

MainWindow.xaml相关代码

<Grid x:Name="MatrixItem" Visibility ="Collapsed">
    <Grid.RowDefinitions>
        <RowDefinition Height="149*"/>
        <RowDefinition Height="285*"/>
    </Grid.RowDefinitions>
    <Canvas>
        <dg2d:DataGrid2D x:FieldModifier="public" x:Name="MatrixAdj" 
             VirtualizingPanel.IsVirtualizingWhenGrouping="True"
             Canvas.Left="411" Canvas.Top="20"
             Width="350" Height="289"
             AlternationCount="2"
             UseModifiedDataGridStyle="True"
             ItemsSource2D="{Binding Int2DList}"
             RowBackground="White"
             AlternatingRowBackground="#ebebeb"                       
             Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center" />
    </Canvas>
    <Canvas Margin="4,2,-4,265" Grid.RowSpan="2">
        <dg2d:DataGrid2D x:FieldModifier="public" x:Name="MatrixInc" 
                     Canvas.Left="19" Canvas.Top="20"
                     Width="350" Height="289"
                     AlternationCount="2"
                     UseModifiedDataGridStyle="True"
                     ItemsSource2D="{Binding Int2DList}"
                     RowBackground="White"
                     VirtualizingPanel.IsVirtualizingWhenGrouping="True"
                     AlternatingRowBackground="#ebebeb"                       
                     Background="Transparent" Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Center"/>
    </Canvas>
</Grid>

解决办法

1. 彻底清理DataGrid2D的绑定与资源

仅设置ItemsSource2D = null无法完全释放DataGrid2D内部的UI元素和绑定引用,需进一步清理:

private void MatrixData(object sender, RoutedEventArgs e)
{
    if (MatrixMenu.IsChecked)
    {
        if (DrawingCanvas_Undirected.Visibility == Visibility.Visible || DrawingCanvas_Directed.Visibility == Visibility.Visible)
        {
            GraphItem.Visibility = Visibility.Visible;
        }

        MatrixItem.Visibility = Visibility.Collapsed;

        // 彻底清理DataGrid2D资源
        ClearDataGrid2D(MatrixAdj);
        ClearDataGrid2D(MatrixInc);
        
        MatrixMenu.IsChecked = false;
        // 后台触发GC,不阻塞UI
        Task.Run(() => 
        {
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, true);
            GC.WaitForPendingFinalizers();
        });
    }
}

// 封装清理逻辑
private void ClearDataGrid2D(dg2d.DataGrid2D dataGrid)
{
    dataGrid.ItemsSource2D = null;
    dataGrid.Columns.Clear();
    dataGrid.Rows.Clear();
    dataGrid.DataContext = null;
    // 移除所有子元素
    while (dataGrid.HasItems)
    {
        dataGrid.Items.RemoveAt(0);
    }
}

2. 优化DataGrid2D的虚拟化配置

当前用Canvas作为DataGrid2D的容器,而Canvas不支持UI虚拟化,会一次性渲染所有单元格导致内存暴涨。将容器替换为Grid,并启用完整虚拟化:

<Grid x:Name="MatrixItem" Visibility="Collapsed">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <!-- 邻接矩阵 -->
    <dg2d:DataGrid2D x:Name="MatrixInc" 
                     Width="350" Height="289"
                     AlternationCount="2"
                     UseModifiedDataGridStyle="True"
                     ItemsSource2D="{Binding Int2DList}"
                     RowBackground="White"
                     VirtualizingPanel.IsVirtualizing="True"
                     VirtualizingPanel.VirtualizationMode="Recycling"
                     VirtualizingPanel.IsVirtualizingWhenGrouping="True"
                     AlternatingRowBackground="#ebebeb"                       
                     Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center"/>
    <!-- 关联矩阵 -->
    <dg2d:DataGrid2D x:Name="MatrixAdj" 
                     Grid.Column="1"
                     Width="350" Height="289"
                     AlternationCount="2"
                     UseModifiedDataGridStyle="True"
                     ItemsSource2D="{Binding Int2DList}"
                     RowBackground="White"
                     VirtualizingPanel.IsVirtualizing="True"
                     VirtualizingPanel.VirtualizationMode="Recycling"
                     VirtualizingPanel.IsVirtualizingWhenGrouping="True"
                     AlternatingRowBackground="#ebebeb"                       
                     Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Grid>

3. 优化Canvas绘图逻辑

检查Canvas的绘图代码,避免重复创建绘图对象或残留未清理的元素:

// 切换回图形项前,清空Canvas旧元素
private void SwitchToGraphItem()
{
    DrawingCanvas_Undirected.Children.Clear();
    DrawingCanvas_Directed.Children.Clear();
    // 重新初始化绘图资源(比如复用已创建的Ellipse/Line对象)
    InitializeGraphDrawing();
}

4. 彻底移除矩阵项的UI树(可选)

如果Visibility="Collapsed"仍无法释放足够资源,可在切换时将MatrixItem从父容器中移除,需要显示时再添加:

// 切换到图形项时移除矩阵项
MainGrid.Children.Remove(MatrixItem);
// 切换回矩阵项时重新添加
// MainGrid.Children.Add(MatrixItem);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:54:57