我正在开发Revit的加载项,并希望使用mvvm light。我的问题是该程序运行我的dll,并且我没有app.xaml来将viewmodellocator的单例声明为应用程序的资源,将其声明为资源的最佳方法是什么?
Revit将我的代码作为在我的实现IExternalCommand接口的解决方案中的单独类中声明的命令来运行。我可以在调用MainWindow之前从代码后面设置此资源吗?还是可以将其设置为mainwindow.xaml的资源?
编辑
到目前为止,我们对代码belov进行了整理,但是第一次在该命令上运行时遇到错误,但是在第二次使用该命令时却没有错误。
来自命令类CheckerCommand.cs的示例代码
[Transaction(TransactionMode.Manual)]
public class CheckerCommand : IExternalCommand
{
#region IExternalCommand Members Implementation
public Result Execute(ExternalCommandData revit, ref string message, ElementSet elements)
{
new ViewModelLocator();
MainWindow window = new MainWindow(revit);
try
{
WindowInteropHelper helper = new WindowInteropHelper(window)
{
Owner = Autodesk.Windows.ComponentManager.ApplicationWindow
};
window.ShowDialog();
return Result.Succeeded;
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
// Element selection cancelled.
return Result.Cancelled;
}
catch (Exception e)
{
message = e.ToString();
try
{
MessageBox.Show(message, "Fatal error");
window.Close();
}
catch
{
return Result.Failed;
}
return Result.Succeeded;
}
}
#endregion
}
这是MainWindow.xaml上的一些示例代码
<Window x:Class="QMChecker.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:QMChecker.Views"
xmlns:vm="clr-namespace:QMChecker.ViewModel"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:mvvm="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="QMChecker" Height="700" Width="1200">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/QMChecker;component/Resources/CombinedResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<vm:ViewModelLocator x:Key="Locator"/>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<Binding Path="Main" Source="{StaticResource Locator}"/>
</Window.DataContext>
</Window>
示例代码来自MainWindow.xaml.cs背后的代码
public partial class MainWindow : Window
{
public MainWindow(ExternalCommandData _revit)
{
try
{
InitializeComponent();
}
catch (Exception e)
{
throw e;
}
ServiceLocator.Current.GetInstance<MainViewModel>().Revit = _revit;
}
}
ViewModelLocator.cs中的示例代码
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
///
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<SpatialContainmentViewModel>();
SimpleIoc.Default.Register<SpatialContainmentDemandViewModel>();
SimpleIoc.Default.Register<RunChecksViewModel>();
SimpleIoc.Default.Register<SpatialContainmentParameterSummaryViewModel>();
}
public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } }
public SpatialContainmentViewModel SpatialContainment { get { return ServiceLocator.Current.GetInstance<SpatialContainmentViewModel>(); } }
public SpatialContainmentDemandViewModel SpatialContainmentDemand { get { return ServiceLocator.Current.GetInstance<SpatialContainmentDemandViewModel>(); } }
public RunChecksViewModel RunChecks { get { return ServiceLocator.Current.GetInstance<RunChecksViewModel>(); } }
public SpatialContainmentParameterSummaryViewModel SpatialContainmentParameterSummary { get { return ServiceLocator.Current.GetInstance<SpatialContainmentParameterSummaryViewModel>(); } }
public static void Cleanup()
{
SimpleIoc.Default.Unregister<MainViewModel>();
SimpleIoc.Default.Unregister<SpatialContainmentViewModel>();
SimpleIoc.Default.Unregister<SpatialContainmentDemandViewModel>();
SimpleIoc.Default.Unregister<RunChecksViewModel>();
SimpleIoc.Default.Unregister<SpatialContainmentParameterSummaryViewModel>();
}
}
而且我必须在每个UserControl上使用ResourceDictionary
<UserControl.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator"/>
</ResourceDictionary>
</UserControl.Resources>
[老问题,我知道,但是经过一番搜索,我没有在其他地方找到答案。我只是部分工作了,这就是我所拥有的:
MainWindow.xaml.cs
...
public MainWindow()
{
Resources.Add("Locator", new ViewModelLocator());
InitializeComponent();
}
...
MainWindow.xaml
<Window
...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:AppleCMS.ModelHarvesterAddin"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<local:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</ResourceDictionary>
</Window.Resources>
...
其余是MVVMLight的标准配置。我认为关键在于代码背后的Resources.Add("Locator", new ViewModelLocator());
。
这在运行插件时有效。看起来MVVMLight的设计时数据似乎还行不通。我还没有添加多个视图,但是我怀疑在每个视图中都需要以上视图。