Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF移除一个卡舌不会';不处理内容?_C#_Wpf_Tabs - Fatal编程技术网

C# WPF移除一个卡舌不会';不处理内容?

C# WPF移除一个卡舌不会';不处理内容?,c#,wpf,tabs,C#,Wpf,Tabs,我正在以编程方式将选项卡添加到程序中的TabControl。使用用户控件填充每个选项卡的内容: private void process_addTab(string head, string type) { TabItem tab = new TabItem(); tab.Header = head; switch (type) { case "trophy2": tab.Content = new Scoreboard2(); break;

我正在以编程方式将选项卡添加到程序中的
TabControl
。使用
用户控件填充每个选项卡的内容

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);
    }
}
这似乎也能很好地工作,因为选项卡已被移除。然而,这有点欺骗。在一些控件中,我使用
调度程序运行定时函数。例如,Twitch控件中有一个计时器,它每30秒轮询Twitch API以获取通道信息。如果我移除标签,计时器仍会继续运行;即使它不应该再存在了


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

通常,当用户控件从视口中删除时,WPF不会处理它们。这在某些应用程序中会造成问题(有关更广泛的讨论,请参阅)

要解决更具体的问题(例如停止计时器),请处理
选项卡项
上的
卸载
事件,并在那里禁用计时器(请参阅)

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

//
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
TimerTabItem项=新TimerTabItem();
item.Unloaded+=ItemOnUnloaded;
tabControl.Items.Add(item);
}
私有无效项未加载(对象发送方,RoutedEventArgs RoutedEventArgs)
{
(发送方为TimerTabItem.Dispose();
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
tabControl.Items.Remove(tabControl.Items[0]);
}
}
类TimerTabItem:TabItem,IDisposable
{
私有调度程序MyTimer{get;set;}
public TimerTabItem():base()
{
调度程序计时器=新调度程序();
timer.Interval=新的时间跨度(0,0,0,3);
timer.Tick+=TimerOnTick;
timer.Start();
MyTimer=计时器;
}
私有void TimerOnTick(对象发送方,EventArgs EventArgs)
{
MessageBox.Show(“你好!”);
}
#IDisposable的区域实现
/// 
///执行与释放、释放或重置非托管资源相关的应用程序定义的任务。
/// 
/// 2
公共空间处置()
{
MyTimer.Stop();
MyTimer.Tick-=TimerOnTick;
MyTimer=null;
}
#端区
}

为什么计时器不再存在?调度器拥有对计时器的引用,因此它不会被垃圾收集,框架也不知道为什么要创建它,因此它不会任意停用它。您必须自己禁用它。计时器位于用户控件内,而用户控件位于选项卡项内。。。它被移除了。移除tabitem不应该移除应该移除计时器的用户控件吗?为什么?您所做的只是从可视化树中删除
UserControl
。这并不必然导致它“消失”;它只是将其从显示中删除。只有当内存中没有未完成的引用,并且垃圾收集器已经删除了它时,它才会真正从内存中“消失”。这不会发生在计时器上,因为计时器仍然有一个活动引用(在
调度程序中)。好的,那么我如何处理usercontrol,从而处理调度程序?您可以在移除选项卡时设置
timer.IsEnabled=false
。或者,您可以通过处理选项卡内容的
已加载
已卸载
事件,并分别将
IsEnabled
设置为
来管理其状态。嗯。。。我以我的调度员为例。但是UserControl中还有其他一些元素我需要去掉。是否有一种快速简便的方法来处理UserControl的全部内容?此外,Dispatchermer没有Dispose函数。在Dispatchermer上,可以调用Stop()方法()。对于其他内容,您可以实现IDisposable,编写分解逻辑,然后从事件处理程序调用Dispose?另外,我在某个地方读到WPF不支持IDisposable。只是更新了示例。WPF不支持IDisposable,您仍然需要处理卸载的事件并自己调用Dispose。
/// <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
}