我有一个奇怪的情况,我无法弄清楚。我正在使用MVVM构建从商业软件使用OAPI的程序。我在视图模型中创建了该API的公共字段。然后创建了两个方法,并使用命令将它们绑定到UI中的两个按钮。一种方法负责连接到API,另一种方法负责从商业软件检索数据。第一种方法可以完成工作并与软件建立连接。但是,当我调用第二条命令来检索数据时,出现一个错误,提示您的对象为空。当我再次使用fist命令时,它表示我们已经连接,这意味着我的对象不是null。但第二种方法仍然出现错误。所有方法都是公共的,并且在视图模型中定义。
两个方法都被命令调用
我看不到我在哪里犯错。如果有人可以帮助我,我将不胜感激。最好的问候
在视图模型中,我定义了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为null。另一件事:来自不同用户控件的不同按钮正在使用每个命令。
非常纠结/不完整的代码示例。但是我将尝试以对我友好的实现方式进行突破。我没有确切的解决方案,但是没有什么建议。
我建议使用RelayCommand
中的here类。
RelayCommand.cs-只需将其添加到项目中一次,然后就忘了:)
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
}
然后使用ViewModel
中的用法
private ICommand _getStoryDataFromEtabsCommand;
public ICommand GetStoryDataFromEtabsCommand
=> _getStoryDataFromEtabsCommand ?? (_getStoryDataFromEtabsCommand = new RelayCommand(parameter =>
{
GetStoryDataFromEtabs();
}));
标记
<Button Content="Click me!" Command="{Binding GetStoryDataFromEtabsCommand}"/>
下一个建议是使用断点进行调试。
设置断点:
mySapModel16 = myETABSObject16.SapModel;
} // <== here
然后检查mySapModel16
是否为null
。如果是,则表示myETABSObject16.SapModel
也为null
。然后探索,为什么。
如果以上所有都成功通过,请设置下一个断点
ret = mySapModel16.Story.GetStories(...); // <== here
然后再次检查null
。