2013-03-15 43 views
7

我在WPF應用程序上工作。我在MainWindow.xaml中有一個名爲「Status_label」的標籤。並且我想從其他類(signIn.cs)更改其內容。 通常情況下,我能做到這一點從另一個類和單獨的線程更改WPF mainwindow標籤

var mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(window => window is MainWindow) as MainWindow; 
mainWin.status_lable.Content = "Irantha signed in"; 

但我的問題是,當我試圖通過在signIn.cs類不同的線程訪問它,它給出了一個錯誤:

The calling thread cannot access this object because a different thread owns it. 

我可以通過使用Dispatcher.Invoke(new Action(() =>{..........還是別的來解決這個問題嗎?

編輯: 我要打電話從不同的類此標籤的變化行動,精心爲單獨的線程

MainWindow.xaml

<Label HorizontalAlignment="Left" Margin="14,312,0,0" Name="status_lable" Width="361"/> 

SignIn.cs

internal void getStudentAttendence() 
    { 
     Thread captureFingerPrints = new Thread(startCapturing); 
     captureFingerPrints.Start(); 
    } 

void mySeparateThreadMethod() 
{ 
    var mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(window => window is MainWindow) as MainWindow; 
    mainWin.status_lable.Dispatcher.Invoke(new Action(()=> mainWin.status_lable.Content ="Irantha signed in")); 
} 

l INE VAR孟文返回錯誤The calling thread cannot access this object because a different thread owns it.

請指引我,

謝謝

+0

爲什麼這是低票? – iJay 2013-03-15 06:25:06

+0

也許,因爲這個問題已經回答了一個被人詬病的時代。一些'谷歌搜索'會爲您提供一個合適的解決方案。 – DHN 2013-03-15 07:52:37

回答

22

我解決我的問題,希望有人會需要這個。但不知道這是否是優化的方式。

在我mainWindow.xaml.cs

public MainWindow() 
    { 
     main = this; 
    } 

    internal static MainWindow main; 
    internal string Status 
    { 
     get { return status_lable.Content.ToString(); } 
     set { Dispatcher.Invoke(new Action(() => { status_lable.Content = value; })); } 
    } 

從我SignIn.cs

MainWindow.main.Status = "Irantha has signed in successfully"; 

這工作對我很好。 您可以在這裏找到更多的細節,Change WPF window label content from another class and separate thread

乾杯!

+1

太好了!非常感謝! – MDDDC 2014-12-01 17:17:23

2

試試下面的代碼片段:

status_lable.Dispatcher.Invoke(...) 
+1

感謝您的回覆。但我的問題是由於不同的線程。 – iJay 2013-03-15 07:41:27

+0

不明白你的意思。你是否希望在單獨的線程中這樣做?您可以使用status_lable.Dispatcher.BeginInvoke(...)或 Task.Factory.StartNew(()=> {status_lable.Dispatcher.BeginInvoke(...);});如果你想更有反應 – David 2013-03-15 07:58:10

+0

但我的錯誤返回從var mainWin線,我可以通過另一種方式訪問​​mainWindow的status_label?我編輯了這個問題,你可以檢查一下嗎? – iJay 2013-03-15 08:31:09

1

謝謝!我解決了一個稍微不同的解決方案,但您肯定會指出我的答案是正確的。對於我的應用程序,我在main中有很多控件,並且main上的大多數方法調用都發生在main範圍內,所以使用默認的{get;}方法更簡單。在MainWindow.xaml.cs中設置(或僅在XAML中定義控件)。

在我的父窗口的代碼隱藏中,我在像這樣的單獨線程中啓動MainWindow(簡化示例)。關鍵是要確定主要全球範圍內,即使它被實例化內部Window_Loaded()的:

public ParentWindow() 
    { 
     InitializeComponent(); 
    } 

    MainWindow main; 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     Thread otherThread = new Thread(() => 
     { 
      main = new MainWindow(); 
      main.Show(); 

      main.Closed += (sender2, e2) => 
       main.Dispatcher.InvokeShutdown(); 

      System.Windows.Threading.Dispatcher.Run(); 
     }); 

     otherThread.SetApartmentState(ApartmentState.STA); 
     otherThread.Start(); 

    } 

然後在我的主窗口代碼隱藏,我剛剛與控件進行交互,就好像它是一個簡單的單線程應用程序(在我的情況下,沒有來自子線程的父線程控制)。我可以,但是,控制從這樣父線程主:

private void button_Click(object sender, RoutedEventArgs e) 
     { 
      main.Dispatcher.Invoke(new Action(delegate() 
       { 
        main.myControl.myMethod(); 
       })); 

     } 

通過做這種方式,我避免了定義一切代碼隱藏和使用調度從主窗口的代碼隱藏中的複雜性.xaml.cs。在我的應用程序中,只有少數幾個地方會從父窗口修改main,所以這對我來說更簡單,但您的方法似乎同樣有效。再次感謝!

2

由於答案,他們帶領我走向正確的方向。我結束了這個簡單的解決方案:

public partial class MainWindow : Window 
{ 
    public static MainWindow main; 

    public MainWindow() 
    { 
     InitializeComponent();       
     main = this; 
    } 
} 

然後我在不同thred運行另一個類的事件處理程序:

internal static void pipeServer_MessageReceived(object sender, MessageReceivedEventArgs e) 
    { 
     MainWindow.main.Dispatcher.Invoke(new Action(delegate() 
     { 
      MainWindow.main.WindowState = WindowState.Normal; 
     })); 
    } 

這顯示了最小化窗口時通過namedPipeline收到我的消息。

相關問題