WPF删除选项卡不会处置内容?

时间:2014-11-10 16:23:31

标签: c# wpf tabs

我正在逐步向我的程序中的TabControl添加标签。使用UserControl

填充每个标签的内容
private void process_addTab(string head, string type)
{
    TabItem tab = new TabItem();
    tab.Header = head;

    switch (type)
    {
        case "trophy2": tab.Content = new Scoreboard2(); break;
        case "trophy4": tab.Content = new Scoreboard4(); break;
        case "text": tab.Content = new TextFields(); break;
        case "talk": tab.Content = new LowerThirds(); break;
        case "image": tab.Content = new ImageSelect(); break;
        case "timer": tab.Content = new Timer(); break;
        case "hitbox": tab.Content = new Hitbox(); break;
        case "twitch": tab.Content = new Twitch(); break;
        case "twitter": tab.Content = new Twitter(); break;
        case "ustream": tab.Content = new Ustream(); break;
    }

    tabControl.Items.Add(tab);
}

这很有效。但是,当我从TabControl中删除标签时,会出现此问题。每个选项卡中都有一个按钮,用于从控件中删除该特定选项卡:

public static void RemoveClick(TabControl tabControl)
{
    if (MessageBox.Show("Are you sure you wish to remove this tab?", "Remove Tab",
        MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
    {
        TabItem item = (TabItem)tabControl.SelectedItem;
        tabControl.Items.Remove(tabControl.SelectedItem);
    }
}

这似乎也很有效,因为删除了标签。但是,它有点欺骗。在一些控件中,我有一个DispatcherTimer的定时函数。例如,Twitch控件在控件中有一个计时器,它每隔30秒轮询一次Twitch API以获取通道信息。如果我删除标签,计时器仍然继续运行;即使它不再存在。

知道怎么解决这个问题吗?假装我不太了解C#;因为我没有。

1 个答案:

答案 0 :(得分:1)

通常,WPF在从视口中删除时不会丢弃用户控件。这会导致某些应用程序出现问题(请参阅Disposing WPF User Controls进行广泛的讨论)。

要解决更具体的问题(例如停止计时器),请处理Unloading上的TabItem事件,并在那里停用计时器(http://msdn.microsoft.com/en-us/library/system.windows.controls.tabitem(v=vs.110).aspx)。

这是一个高级示例(子类化TabItem仅作为封装计时器的示例):

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TimerTabItem item = new TimerTabItem();
        item.Unloaded += ItemOnUnloaded;
        tabControl.Items.Add(item);
    }

    private void ItemOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
    {
        (sender as TimerTabItem).Dispose();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        tabControl.Items.Remove(tabControl.Items[0]);
    }
}

class TimerTabItem : TabItem, IDisposable
{
    private DispatcherTimer MyTimer { get; set; }

    public TimerTabItem() : base()
    {
        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = new TimeSpan(0, 0, 0, 3);
        timer.Tick += TimerOnTick;
        timer.Start();
        MyTimer = timer;
    }

    private void TimerOnTick(object sender, EventArgs eventArgs)
    {
        MessageBox.Show("Hello!");
    }

    #region Implementation of IDisposable

    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    /// <filterpriority>2</filterpriority>
    public void Dispose()
    {
        MyTimer.Stop();
        MyTimer.Tick -= TimerOnTick;
        MyTimer = null;
    }

    #endregion
}