当我尝试使用 MVVM WPF 中的命令修改对象时,为啥在视图模型中出现空错误?
Posted
技术标签:
【中文标题】当我尝试使用 MVVM WPF 中的命令修改对象时,为啥在视图模型中出现空错误?【英文标题】:Why I get null error for my object in view model when I try to modify it with command in MVVM WPF?当我尝试使用 MVVM WPF 中的命令修改对象时,为什么在视图模型中出现空错误? 【发布时间】:2020-07-29 14:32:25 【问题描述】:我有一个奇怪的情况,我无法弄清楚。 我正在使用 MVVM 构建一个使用商业软件中的 OAPI 的程序。 我在我的视图模型中创建了该 API 的公共字段。然后我创建了两个方法并使用命令将它们绑定到我的 UI 中的两个按钮。 其中一种方法负责连接到 API,另一种方法负责从商业软件中检索数据。 第一种方法完成工作并连接到软件。但是当我调用第二个命令来检索数据时,我收到一个错误,指出您的对象为空。 当我再次使用第一个命令时,它说我们已经连接,这意味着我的对象不为空。但我仍然在第二种方法中遇到错误。所有方法都是公共的,并在视图模型中定义。
两个方法都被命令调用
我看不出我在哪里犯了错误。 如果有人可以帮助我,我将不胜感激。 最好的问候
在视图模型中,我定义了 OAPI 所需的这些属性
//dimension the ETABS Object as cOAPI type
public ETABSv1.cOAPI myETABSObject get; set;
public ETABS2016.cOAPI myETABSObject16 get; set;
public ETABSv1.cSapModel mySapModel get; set;
public ETABS2016.cSapModel mySapModel16 get; set;
这是我的 Cammand 课程:
internal class GetStoryDataFromEtabsCommand : ICommand
private MainWindowViewModel _viewModel;
public GetStoryDataFromEtabsCommand(MainWindowViewModel viewModel)
_viewModel = viewModel;
public event EventHandler CanExecuteChanged
add CommandManager.RequerySuggested += value;
remove CommandManager.RequerySuggested -= value;
public bool CanExecute(object parameter)
return true;
public void Execute(object parameter)
_viewModel.GetStoryDataFromEtabs();
还有另一个与上面完全相同的命令,但调用了 ConnectToEtabs() 方法
这是我的 ConnectToEtabs() 方法:
public void ConnectToEtabs()
//get the active ETABS object
myETABSObject16 =
(ETABS2016.cOAPI) System.Runtime.InteropServices.Marshal.GetActiveObject
("CSI.ETABS.API.ETABSObject");
//Get a reference to cSapModel to access all API classes and functions
mySapModel16 = myETABSObject16.SapModel;
这是我的 GetStoryDataFromEtabs() 方法:
public void GetStoryDataFromEtabs()
double BaseElev = 0;
string[] notneededst = null;
int NumOfStory = 0;
double[] storyElev = null;
double[] notneededd = null;
Boolean[] notneededbool = null;
int[] notneededint = null;
ret = mySapModel16.Story.GetStories(ref NumOfStory, ref notneededst, ref
storyElev, ref notneededd, ref notneededbool, ref notneededst, ref
notneededbool, ref notneededd);
earthQuake.NumberOfStory = NumOfStory;
earthQuake.BuildingHeight = Math.Round((storyElev[NumOfStory] -
storyElev[0]), 2);
在 GetStoryDataFromEtabs() 方法中,mySapModel16 为空。 另一件事:每个命令都被来自不同用户控件的不同按钮使用。
【问题讨论】:
“我看不出哪里出错了”——我们也是。请向我们展示您的代码的相关部分。 您好,欢迎来到论坛。水晶球和千里眼供不应求,但我猜我会说每个命令都会触发一个任务来执行您的处理,而第二个命令没有对某事实例的有效引用。 你好亲爱的@Clemens,谢谢你的回复。你说得对。我编辑了我的问题以包含我的代码。 【参考方案1】:我认为这行可能是您抛出错误的地方,您能确认一下吗?
ret = mySapModel16.Story.GetStories(ref NumOfStory, ref notneededst, ref
storyElev, ref notneededd, ref notneededbool, ref notneededst, ref
notneededbool, ref notneededd);
我的推理是双重的,
ref
类型必须在传入之前进行初始化
功能。
您稍后将使用其中一种引用类型:
earthQuake.BuildingHeight = Math.Round((storyElev[NumOfStory] -
storyElev[0]), 2);
如果您的函数 mySapModel16.Story.GetStories(…)
初始化了您传递给它的参数,那么您应该改用 out
。
另一方面,您应该考虑让您的 ViewModel 实现您要绑定到的 ICommand 属性并让它触发一个任务,例如
public ICommand GetStoryDataFromEtabsCommandget;set;
public bool IsConnectedget;private set;
在构造函数中
GetStoryDataFromEtabsCommand = new Command(()=>GetStoryDataFromEtabs(), ()=>IsConnected);
一旦您的连接函数执行了连接,就会设置IsConnected
。
然后
public void GetStoryDataFromEtabs()
变为 public Task GetStoryDataFromEtabs()
。如果您发现需要很长时间,这将允许您使函数异步并等待对mySapModel16.Story.GetStories(…)
的调用。
【讨论】:
这个商业软件的API工作方式是,我应该首先定义myEtabsObject16,它是Visual Studio中引用的EtabsObject16类型。它是一个 COM 对象。然后是 sapModel ,我必须为其创建一个实例。那将是 mySapModel。问题是用户应该能够在需要时连接到 Etabs 软件。没关系。有用。用户还应该能够随时获取数据。所以它应该是另一个命令。它是从另一个用户控件调用的。但是当他这样做时 myEtabsObject 为空!哪个第一个命令启动它。为什么 所以它没有达到运行这一行的目的:ret = mySapModel16. .... 因为 mySapModel16 为空。 我看到您的 ViewModel 是您的 Command 类的属性,而不是相反。您拥有的两个 Command 实例是否有可能没有引用同一 ViewModel 实例?以上是关于当我尝试使用 MVVM WPF 中的命令修改对象时,为啥在视图模型中出现空错误?的主要内容,如果未能解决你的问题,请参考以下文章
我在使用 MVVM for WPF 实现命令处理器模式时遇到问题