在没有app.xaml声明的项目上使用viewmodellocator

时间:2017-06-22 14:50:01

标签: c# mvvm-light

我正在研究Revit的加载项,并希望使用mvvm light。我的问题是该程序运行我的DLL并且我没有app.xaml来声明viewmodellocator的单例作为应用程序的资源,将此声明为资源的最佳方法是什么?

Revit将我的代码作为在我的解决方案中实现IExternalCommand接口的单独类中声明的命令运行。我可以在调用MainWindow之前从代码中设置此资源吗?或者我可以将其设置为mainwindow.xaml的资源吗?

EDITED

到目前为止,我们已经编写了代码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>

1 个答案:

答案 0 :(得分:0)

我知道有个老问题,但是经过一番搜索,我没有在其他地方找到答案。我只是部分工作了,这就是我所拥有的:

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的设计时数据似乎还行不通。我还没有添加多个视图,但是我怀疑在每个视图中都需要以上视图。