Adding event to Context Menu causes memory leak

6 posts, 1 answers
  1. danparker276
    danparker276 avatar
    389 posts
    Member since:
    Aug 2010

    Posted 21 Jun 2011 Link to this post

    I have an OOB app that will call a RadChildWindow that contains a RichTextBox.  I get a memory leak when I repopulate the content of the window, or if I close it and reopen it again.  This only happens when add a showing or closing event to the context menu.  I moved it to a empty control like below and it still caused memory leaks.  pressing a button to populate the child window 50 times will make the memory balloon to 500k or so.  Also, if I minimize the application, the memory seems to clear.  Just populate a radchildwindow with the code below and you should see the problem.
    public BlankControl()
    {
        InitializeComponent();
        Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = (Telerik.Windows.Controls.RichTextBoxUI.ContextMenu)this.rrtbDescription.ContextMenu;
        contextMenu.ContentBuilder = new CustomMenuBuilder(this.rrtbDescription);
        contextMenu.Showing += new EventHandler<ContextMenuEventArgs>(contextMenu_Showing);
        contextMenu.Closed += new EventHandler(contextMenu_Closed);
    }
    void contextMenu_Closed(object sender, EventArgs e)
    {
    }
    void contextMenu_Showing(object sender, ContextMenuEventArgs e)
    {
    }
    <Grid x:Name="LayoutRoot" Margin="2">
        <telerik:RadRichTextBox Name="rrtbDescription" Grid.Row="4" Width="600" Height="200" Margin="0,10,0,0"
                        DataContext="{Binding}"     IsSpellCheckingEnabled="True"
                        BorderThickness="1" BorderBrush="Black" IsSelectionMiniToolBarEnabled="False"
                        IsContextMenuEnabled="True" 
                        AcceptsTab="False" AcceptsReturn="False"
                        >
     
            <telerik:RadRichTextBox.Effect>
                <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
            </telerik:RadRichTextBox.Effect>
     
        </telerik:RadRichTextBox>
    </Grid>

  2. danparker276
    danparker276 avatar
    389 posts
    Member since:
    Aug 2010

    Posted 21 Jun 2011 Link to this post

    Oh, I'm also using the custom menu builder.  Adding this doesn't cause the memory leak, but I should probably add it to the post.

    public class CustomMenuBuilder : ContextMenuContentBuilder
    {
        private RadRichTextBox rrtb = new RadRichTextBox();
     
        public CustomMenuBuilder(RadRichTextBox rrtb)
            : base(rrtb)
        {
            this.rrtb = rrtb;
     
        }
        protected override ContextMenuGroup CreateTextEditCommands()
        {
            return new ContextMenuGroup();
        }
     
    }
  3. DevCraft banner
  4. Alex
    Admin
    Alex avatar
    129 posts

    Posted 23 Jun 2011 Link to this post

    Hello danparker276,

    There is indeed memory leak caused by the attached event handlers. Let me clarify things a bit. Whenever new RadRichTextBox is created an instance of ContextMenu is assigned for it. This is instance is created by MEF at run time and is shared between all rich text boxes instances. Also the instance of the ContextMenu is cached by MEF and it is never garbage collected in order to be ready to use whenever new rich text boxes are created.

    So what happens in your scenario is that every time you add an event handler to the Closed event inside the BlankControl class, you are adding this event handler to the same context menu that is cached by MEF and is never collected. This is prevents current instance of the BlankControl itself  to be garbage collected because the assigned event handler connects it to cached the context menu.
    That said, you have two options to avoid the leak:
    1. Modify you application so that the events you attach to the context menu are detached when the control that uses them is no longer needed.
    2. When you create RadRichTextBox assigne to it a new instance of a Telerik.Windows.Controls.RichTextBoxUI.ContextMenu class. This is the way, the event handlers you attach to it will not hold a reference to the context menu created by MEF (which is not collected) and will not prevent you control from being garbage collected.

    I hope this helpful. Do not hesitate to send us a support ticket if you need more specific help.

    Best wishes,
    Alex
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  5. danparker276
    danparker276 avatar
    389 posts
    Member since:
    Aug 2010

    Posted 23 Jun 2011 Link to this post

    How can I detach the events when the Child window is closed?

    for #1:
    how could I remove the events from the closed events?:
            void myRadWindow_Closed(object sender, WindowClosedEventArgs e)
            {

    and for #2:
    I'm creating it in the xaml, how would I assign a new instance of the Telerik.Windows.Controls.RichTextBoxUI.ContextMenu class?
    Are you saying do this:
                        Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = new Telerik.Windows.Controls.RichTextBoxUI.ContextMenu();
                        rrtbDescription.ContextMenu = contextMenu;

    This didn't work.


    I basically just want to check if the context menu has focus.  That's all I'm using it for.  Is there another way to check, other that creating events for it.
  6. danparker276
    danparker276 avatar
    389 posts
    Member since:
    Aug 2010

    Posted 23 Jun 2011 Link to this post

    I've tried the following, but it didn't work
                var aaa = myRadWindow.ChildrenOfType<RadRichTextBox>();
                foreach (RadRichTextBox a in aaa)
                {
     
                    Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = (Telerik.Windows.Controls.RichTextBoxUI.ContextMenu)a.ContextMenu;
                    contextMenu.Showing -= null;
                    contextMenu.Closed -= null;
                    contextMenu = null;
    ...
    or just
                    a.ContextMenu = null;
     
                }
    also tried
    WindowData wd= (WindowData ) this.myRadWindow.DataContext;
     
              var aaa = this.myRadWindow.ChildrenOfType<RadRichTextBox>();
              foreach (RadRichTextBox a in aaa)
              {
                  Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = (Telerik.Windows.Controls.RichTextBoxUI.ContextMenu)a.ContextMenu;
                  contextMenu.Showing -= new RoutedEventHandler(wd.contextMenu_Showing);
     
    it didn't like that though
  7. Answer
    Alex
    Admin
    Alex avatar
    129 posts

    Posted 29 Jun 2011 Link to this post

    Hi danparker276,

    I've attached a sample project which shows one way of how the detaching of the events can be done. Basically, the detaching is done in the DetachFromEvents() method of the BlankControl and this method is called whenever the RadWindow is closed.

    I hope this is helpful. If you need further assistance please don't hesitate to open support ticket and send as a sample project so we can provide a more specific solution.

    All the best,
    Alex
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top
DevCraft banner