所以基本上我有一个MainWindow
,一个类SetupViewModel
在一个单独的cs文件中定义,另一个类ImageViewModel
在一个单独的cs文件中;
我想知道无论如何我可以从MainWindow
调用ImageViewModel
中的操作。更多详情如下:
,调用MainWindow中的更改如下(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
中的调用代码:
试 { 动作SwitchTo2DView = delegate() { ((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 :(得分:3)
我敢打赌,在调用它时,你的DataContext为空的五块钱。这意味着它可能被称为太早。这可能意味着你应该在Dispatcher上推送你正在做的任何事情。
虽然您可能假设您的应用程序在调用此方法时已完全加载,但未必如此。要对此进行测试,请在调试期间设置断点并检查DataContext
以查看它是否为空。
如果为null,则有两个选择。首先,回归。根据方法的调用方式,可以在加载期间多次调用。稍后的调用可能会显示非空的上下文。
另一个选项是在加载应用程序后使用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);
}