WPF移除选项卡不会释放内容?

14 浏览
0 Comments

WPF移除选项卡不会释放内容?

我在程序中动态地向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#,因为我确实不太了解。

admin 更改状态以发布 2023年5月23日
0
0 Comments

通常情况下,当WPF从视口中移除用户控件时,它不会将其释放。这会在一些应用程序中造成麻烦(有关更广泛的讨论,请参见释放WPF用户控件)。

要解决您更具体的问题(例如停止计时器),请处理TabItem上的Unloading事件,在那里禁用计时器(请参见https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.tabitem)。

这是一个高级示例(子类化TabItem只是为了演示封装定时器):

/// 
/// Interaction logic for MainWindow.xaml
/// 
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
    /// 
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// 
    /// 2
    public void Dispose()
    {
        MyTimer.Stop();
        MyTimer.Tick -= TimerOnTick;
        MyTimer = null;
    }
    #endregion
}

0