简体   繁体   English

WPF数据网格中的内存泄漏问题

[英]Memory leak issue in WPF datagrid

I had develop an application which have an datagrid and it has different context menu for column header and rows. 我开发了一个具有datagrid的应用程序,它具有不同的列标题和行的上下文菜单。 Now for header context menu there in an I have filter the datagrid columns. 现在对于标题上下文菜单,我已经过滤了datagrid列。 The code snippet is below. 代码片段如下。

<DataGrid   Padding="3" BorderBrush="SkyBlue" BorderThickness="1"  ItemsSource="{Binding Source={StaticResource cvsCoreData}}"   SelectionUnit="FullRow" IsReadOnly="True"  AutoGenerateColumns="False" x:Name="Data"  Margin="0,5,0,28">
    <DataGrid.Resources>
        <ContextMenu  x:Key="DataGridColumnHeaderContextMenu" >
            <MenuItem Header="ABC" Click="ABC_Click" />
            <MenuItem Header="EFG" Click="EFG_Click" />
            <MenuItem Header="HIJ" Click="HIJ_Click" />
            <MenuItem Header="KLM" Click="KLM_Click" />
        </ContextMenu>
    </DataGrid.Resources>
    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True" >
                    <Setter Property="Background" Value="SkyBlue" />
                    <Setter Property="Foreground" Value="Black"/>
                </Trigger>
            </Style.Triggers>
            <Setter Property="ContextMenu"
            Value="{StaticResource DataGridColumnHeaderContextMenu}" />
        </Style>
    </DataGrid.RowStyle>
    <DataGrid.Columns>
        <DataGridTemplateColumn SortMemberPath="Key" Width="*" Header="Key ">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock x:Name="block"  TextWrapping="Wrap" Text="{Binding Key}">

                    </TextBlock>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Width="*" Header="Lerm Description" Binding="{Binding KeyDescription}" />
        <DataGridTextColumn Width="*" Header="Short " Binding="{Binding Short}" />
        <DataGridTextColumn Width="*" Header="Rule" Binding="{Binding Rules}" />
    </DataGrid.Columns>
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem x:Name="ContextKey" IsCheckable="True" IsChecked="True" Header="Key" Unchecked="ContextMenu_Unchecked" Checked="ContextMenu_Checked" Tag="0" />
            <MenuItem x:Name="ContextLermDescription" IsCheckable="True" IsChecked="True" Header="Key" Unchecked="ContextMenu_Unchecked" Checked="ContextMenu_Checked" Tag="1"  />
            <MenuItem x:Name="ContextShor" IsCheckable="True" IsChecked="True" Header="Short" Unchecked="ContextMenu_Unchecked" Checked="ContextMenu_Checked" Tag="2"  />
            <MenuItem x:Name="ContextRule" IsCheckable="True" IsChecked="True" Header="Rules" Unchecked="ContextMenu_Unchecked" Checked="ContextMenu_Checked" Tag="3"  />
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>  

Now when the header context menu unchecked the particular column will be hidden and vice versa. 现在,当未选中标题上下文菜单时,将隐藏特定列,反之亦然。 It works fine but when I wanted to hide the last column I takes about 5 sec and it allocate a large amount of memory. 它运行正常,但是当我想隐藏最后一列时,我花了大约5秒钟,它分配了大量的内存。 Same thing is happening when I make visible first column after hiding all the columns in the datagrid. 当我在隐藏数据网格中的所有列之后创建可见的第一列时,会发生同样的事情。 Why this memory leak is happening. 为什么会发生内存泄漏

Memory leaks are a hazard when working with context menus -- especially when attaching them to grids (I have had a similar issue in the past). 使用上下文菜单时,内存泄漏是一种危险 - 特别是在将它们附加到网格时(我过去遇到了类似的问题)。 In the comments you mentioned that you isolated the problem to the DataGridRow Style: 在您提到的评论中,您将问题隔离到DataGridRow样式:

<Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderContextMenu}" />

I don't know exactly why the above causes a memory leak, but it does look like a risky thing to do. 我不知道为什么上面会导致内存泄漏,但它看起来确实很危险。 You're attaching the static object ("DataGridColumnHeaderContextMenu") -- meaning it cannot be disposed -- to every row in the Grid. 您将静态对象(“DataGridColumnHeaderContextMenu”) - 意味着它无法处理 - 附加到网格中的每一行。 All it takes for that to leak is for the context menu to hold a reference to the row, and for the row to be recycled. 泄漏所需要的只是上下文菜单保存对行的引用,以及要回收的行。

Anyway, what I think you should do in this case (and in this kind of scenario in general) is to use events to attach the context menu when the row loads, and detach it when it unloads. 无论如何,我认为你应该在这种情况下(以及在这种情况下)应该做的是在行加载时使用事件附加上下文菜单,并在卸载时分离它。 For DataGrid rows, this means you should attach the context menu in the DataGrid.LoadingRow event, and remove it in the UnloadingRow event. 对于DataGrid行,这意味着您应该在DataGrid.LoadingRow事件中附加上下文菜单,并在UnloadingRow事件中将其删除。 This should ensure that no menu leak will occur. 这应该确保不会发生菜单泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM