2014-08-27 6 views
3

У меня было разработано приложение, имеющее datagrid, и у него есть другое контекстное меню для заголовков и строк столбца. Теперь для контекстного меню заголовка в моем фильтре есть столбцы datagrid. Ниже приведен фрагмент кода.Ошибка утечки памяти в WPF datagrid

<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> 

Теперь, когда контекстное меню заголовка не отмечено, конкретный столбец будет скрыт и наоборот. Он отлично работает, но когда я хотел скрыть последний столбец, мне понадобится около 5 секунд, и он выделяет большой объем памяти. То же самое происходит, когда я делаю видимый первый столбец, скрывая все столбцы в datagrid. Почему это утечка памяти происходит.

+0

какой .net структура вы используете? 3.5 или 4.0 или ... – blindmeis

+0

Я использую .NET 4.5 framework. –

+0

Ну, у меня была аналогичная проблема с DataGridTemplateColumn. (http://wpf.codeplex.com/discussions/400881), но это решено с помощью 4.5 – blindmeis

ответ

5

Утечки памяти представляют опасность при работе с контекстными меню - особенно при прикреплении их к сеткам (у меня была аналогичная проблема в прошлом). В комментариях вы упомянули, что вы изолировали проблему в DataGridRow Style:

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

Я не знаю точно, почему выше вызывает утечку памяти, но это выглядит как рискованная вещь, чтобы сделать. Вы прикрепляете статический объект («DataGridColumnHeaderContextMenu»), что означает, что он не может быть удален - для каждой строки в Grid. Все, что требуется для утечки, заключается в том, что контекстное меню содержит ссылку на строку, а для строки, подлежащей переработке.

В любом случае, я думаю, что вам следует делать в этом случае (и в этом виде сценария в целом) использовать события, чтобы прикрепить контекстное меню при загрузке строки и отсоединить ее при ее разгрузке. Для строк DataGrid это означает, что вы должны приложить контекстное меню в событии DataGrid.LoadingRow и удалить его в событии UnloadingRow. Это должно гарантировать, что утечка меню не произойдет.

Смежные вопросы