当我尝试使用 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 实现命令处理器模式时遇到问题

WPF中MVVM子窗口修改数据问题

为什么必须公开ICommand对象才能在WPF中正常工作?

Wpf MVVM ViewModel怎么控制View呢?

我需要导航到另一个视图,其中包含带有 MVVM 的 WPF 中父对象的子对象

WPF 如何将主题应用于使用 MVVM 动态创建的对象