2011-11-11 38 views
0

我正在开发一个多线程应用程序,为每个新线程打开一个新的“可关闭”选项卡。我从this site得到可关闭tabitems的代码,但我也希望在tabitem中有一个文本框。我厌倦了在运行时从main方法中添加文本框,但它不能从之后创建的线程访问。做这项工作的最佳方式是什么?我正在寻找将文本框添加到可从其他工作线程编辑的可关闭选项卡的最佳方式。关闭tabitem。如何添加文本框?

编辑: 我已经添加了一些示例代码来显示我想要实现的。

namespace SampleTabControl 
{ 
    public partial class Window1 : Window 
    { 
    public static Window1 myWindow1; 

    public Window1() 
    { 
     myWindow1 = this; 
     InitializeComponent(); 
     this.AddHandler(CloseableTabItem.CloseTabEvent, new RoutedEventHandler(this.CloseTab));  
    } 

    private void CloseTab(object source, RoutedEventArgs args) 
    { 
     TabItem tabItem = args.Source as TabItem; 
     if (tabItem != null) 
     { 
     TabControl tabControl = tabItem.Parent as TabControl; 
     if (tabControl != null) 
      tabControl.Items.Remove(tabItem); 
     } 
    } 

    private void btnAdd_Click(object sender, RoutedEventArgs e) 
    { 
     Worker worker = new Worker(); 

     Thread[] threads = new Thread[1]; 
     for (int i = 0; i < 1; i++) 
     { 
     TextBox statusBox = new TextBox(); 

     CloseableTabItem tabItem = new CloseableTabItem(); 
     tabItem.Content = statusBox; 
     MainTab.Items.Add(tabItem); 

     int index = i; 
     threads[i] = new Thread(new ParameterizedThreadStart(worker.start)); 
     threads[i].IsBackground = true; 
     threads[i].Start(tabItem); 
     }  
    } 
    } 
} 

而这是Worker类。

namespace SampleTabControl 
{ 
    class Worker 
    { 
    public CloseableTabItem tabItem; 

    public void start(object threadParam) 
    { 
     tabItem = (CloseableTabItem)threadParam; 
     Window1.myWindow1.Dispatcher.BeginInvoke((Action)(() => { tabItem.Header = "TEST"; }), System.Windows.Threading.DispatcherPriority.Normal); 
     //Window1.myWindow1.Dispatcher.BeginInvoke((Action)(() => { tabItem.statusBox.Text //statusbox is not accesible here= "THIS IS THE TEXT"; }), System.Windows.Threading.DispatcherPriority.Normal); 

     while (true) 
     { 
     Console.Beep(); 
     Thread.Sleep(1000); 
     } 
    } 

    } 
} 

在我注释掉的行中,statusBox不可访问。

最好的问候!

回答

0

看到您的编辑后,很明显我的原始文章没有回答原始问题。

我认为要以您希望将tabItem.Content投射到文本框的方式访问文本框。

类似下面可以工作

TextBox t = tabItem.Content as TextBox; 
if (t != null) 
    Window1.myWindow1.Dispatcher.BeginInvoke((Action)(() => { t.Text = "THIS IS THE TEXT";}), System.Windows.Threading.DispatcherPriority.Normal); 
+0

是的,我知道调度程序,但是当我在运行时将文本框添加到可关闭选项卡时,它无法访问。我将添加一些示例代码,以便您可以看到。 – Arya

+0

“TextBox t = tabItem.Content as TextBox;”使运行时程序崩溃。 – Arya

+0

我刚刚检查了错误消息,这就是它所说的“调用线程不能访问此对象,因为不同的线程拥有它。”你能告诉我如何解决它吗? – Arya

0

WPF不能修改在不同的线程创建的,那么当前一个

如果您还没有准备好项目,我会强烈建议你看看MVVM设计模式。这将UI层与业务逻辑层分开。您的应用程序将成为您的ViewModel类,而UI层(视图)只是一个非常漂亮的界面,可让用户轻松与ViewModel进行交互。

这意味着您的所有UI组件都将共享一个线程,而您的较长时间运行的进程(如检索数据或处理数字)可以安全地在后台线程上完成。

例如,你可以结合你的TabControl.ItemsSourceObservableCollection<TabViewModels>,当你执行AddTabCommand你将开始一个新的后台工作,以新的TabViewModel添加到收藏MainViewModel.TabViewModels

一旦后台工作完成它的工作。 UI会自动通知该集合中有一个新项目,并将使用您指定的任何DataTemplate为您绘制新的TabItem,其中包括TabControl