2013-05-07 83 views
2

所以基本上我有一個MainWindow,一個類別SetupViewModel在一個單獨的cs文件中定義,另一個類ImageViewModel在一個單獨的cs文件中; 我想知道有無論如何我可以從ImageViewModel調用MainWindow的操作。詳情如下:線程調用主窗口?

  • 在ImageViewModel

    ,調用在主窗口的變化如下(在MainWindow以下代碼):

    this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, 
           new Action(
            delegate() 
            { 
              ((SetupViewModel)this.DataContext).ViewType = Convert.ToInt32(ViewTypes.ViewType2D); 
            } 
           ) 
          ); 
    
  • 的ViewType變量在SetupViewModel定義如下

    private int _viewType; 
        public int ViewType 
        { 
         get 
         { 
          return _viewType; 
         } 
         set 
         { 
          _viewType = value; 
          OnPropertyChanged("ViewType"); 
         } 
        } 
    
  • 這是我做過的,但沒有成功;在ImageViewModel的invoke代碼:

    嘗試 { 行動SwitchTo2DView =委託() { ((CaptureSetupViewModel)System.Windows.Application.Current.MainWindow.DataContext).ViewType = Convert.ToInt32(ViewTypes.ViewType2D) ; };

      System.Windows.Application.Current.MainWindow.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, SwitchTo2DView); 
         } 
         catch (Exception ex) 
         { 
          Console.WriteLine("Caught exception: " + ex.ToString()); 
         } 
    

和異常:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. 
    at CaptureSetupDll.ViewModel.LiveImageViewModel.<StartZStackPreview>b__2c() 
    --- End of inner exception stack trace --- 
    at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) 
    at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) 
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) 
    at System.Delegate.DynamicInvokeImpl(Object[] args) 
    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) 
    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) 
    at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) 
    at System.Windows.Threading.DispatcherOperation.InvokeImpl() 
    at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) 
    at System.Threading.ExecutionContext.runTryCode(Object userData) 
    at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Windows.Threading.DispatcherOperation.Invoke() 
    at System.Windows.Threading.Dispatcher.ProcessQueue() 
    at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) 
    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) 
    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) 
    at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) 
    at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) 
    at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg) 
    at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) 
    at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) 
    at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) 
    at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) 
    at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout) 
    at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) 
    at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method) 
    at CaptureSetupDll.ViewModel.LiveImageViewModel.StartZStackPreview() 

我是外行到C#;任何想法我如何能做到這一點?非常感謝。

+0

有什麼的InnerException及其堆棧跟蹤? – SLaks 2013-05-07 16:26:12

+0

我如何找到它們? – 2013-05-07 16:27:48

+0

Visual Studio打開時顯示的異常窗口將提供此信息。你正在做的是從第二個線程調用MainWindow的正確方法。 – 2013-05-07 16:33:54

回答

3

我打賭你五個錢,你的DataContext在調用時是空的。這意味着它可能被稱爲太早。這可能意味着你應該推動你在Dispatcher上做的任何事情。

雖然你可能假設你的應用程序在調用這個方法時被完全加載,但它不一定是真的。要測試這個,在調試過程中設置一個斷點並檢查DataContext以查看它是否爲空。

如果它爲空,則有兩種選擇。首先,回來。根據調用方法的不同,可能會在加載過程中多次調用該方法。稍後的調用可能會顯示非空的上下文。

另一種選擇是在加載應用程序後,使用Dispatcher稍後重新調用該方法。

這裏有一個小的僞代碼看起來有點像C#,甚至可能編譯:

public void CheckTheDataContext() 
{ 
    // is it null? 
    if(this.DataContext == null) 
    { 
     // then drop an Action re-invoking this method later 
     // when the application idles out a bit 
     Dispatcher.BeginInvoke((Action)(() => 
     { 
      CheckTheDataContext(); 
     }), System.Windows.Threading.DispatcherPriority.ApplicationIdle); 
     return; 
    } 
    DoSomethingElseWithTheContext(DataContext); 
} 
+1

這完全有道理。非常感謝Will :) – 2013-05-07 20:17:41