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
}