Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. Now for header context menu there in an I have filter the datagrid columns. 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. Same thing is happening when I make visible first column after hiding all the columns in the datagrid. Why this memory leak is happening.

like image 334
Sowvik Roy Avatar asked Dec 02 '25 17:12

Sowvik Roy


1 Answers

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:

<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. 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. This should ensure that no menu leak will occur.

like image 151
McGarnagle Avatar answered Dec 05 '25 15:12

McGarnagle



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!