Wednesday, April 20, 2011

Problems closing tabs

I've a WPF app organized with tabs. I added a small button to each tabitem header that allow the user to close the tab.

When the user click on the small button, I remove the tabItem from the tabControl.

tabControl.Items.Remove(tabItem);

As result of this the tabItem dissapears, and that is fine, but here comes the problem:

The TabItem is not visible(good), but it still exists(bad). If I put a timer inside, the timer execucutes his Tick, and more important, if I've a datagrid with 200.000 records and I close the Tab, The garbage collector don't release the memory as I expected.

I asked google about the problem and I've implemented some of the advices described. It didn't work.

Can anyone help me? Thanks

From stackoverflow
  • Place a user control in your tab, and in the Usercontrol code, handle its own "Unloaded" event.

    In there you should be able to clean-up. (unless your timer is preventing the control from unloading, but last time I tried something similar it worked).

    And yes, WPF is very dangerous for all those things, if you are not careful you can bleed controls pretty fast...

  • This is what I've been using, and as far as I can tell it removes the tabitem from memory. The problem with leaving a timer inside of the tabitem, is that the GC won't collect and dispose of it because it detects that the timer is still in use.

    The Code:

    namespace Reports.Controls
    {
        /// <summary>
        /// Interaction logic for Test.xaml
        /// </summary>
        public partial class ReportTab : TabItem
        {
            public delegate void CloseEvents(ReportTab TabIndex);
            public event CloseEvents Closing;
    
            public ReportTab(string Title)
            {
                InitializeComponent();
                tbTitle.Text = Title;
            }
    
            private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                Closing(this);
            }
        }
    }
    

    The xaml:

    <TabItem x:Class="Reports.Controls.ReportTab"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        >
        <TabItem.Header>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Main" Name="tbTitle" Margin="0,0,8,0"/>
                <Image Height="13" 
                       Source="pack://application:,,/Images/Icons/close.png"
                       MouseLeftButtonUp="Image_MouseLeftButtonUp"/>
            </StackPanel>
        </TabItem.Header>
        <Grid>
             //Tabitem stuff
        </Grid>
    </TabItem>
    

    Here's the page with the Tabcontrol to add a tab:

    void AddTab(string Title)
    {
        Controls.ReportTab rt = new Controls.ReportTab(Title);
        rt.Closing += new Controls.ReportTab.CloseEvents(rt_Closing);
        tabControl.SelectedIndex = tabControl.Items.Add(rt);
    }
    
    /// <summary>
    /// Moves the Tab Control back to the Main tab
    /// after a tab is removed
    /// </summary>
    /// <param name="TabIndex"></param>
    void rt_Closing(Controls.ReportTab TabIndex)
    {
        tabControl.Items.Remove(TabIndex);
        //This resets the tabcontrol back to it's first tabindex
        tabControl.SelectedIndex = 0;
    
    }
    

0 comments:

Post a Comment