Caliburn.Micro 仅 GetAllInstances returns 一个视图模型(Caliburn.Micro MVVM)

Caliburn.Micro GetAllInstances only returns one viewModel(Caliburn.Micro MVVM)

我一直在尝试将 Caliburn.Micro MVVM 框架集成到 C# WPF 项目中,我正处于中间阶段。

我目前只有三个视图模型:

目前,我正在尝试在 AboutView 中使用一个按钮,该按钮绑定到 AboutViewModel 中的 'Chat()' 方法,应该将用户带到 ChatView,但我正在使用 AboutViewModel 对此进行测试。 (如处理程序中所示)

我需要的是所有 Screen/ViewModels 都是单例并且只有一个实例,当我尝试更改页面时,它 returns 到一个已经存在的页面。

这里的问题是,当我执行 IoC.GetAllInstances() 时,我只注册了一个实例,即 ShellViewModel,即使我在引导程序中尝试了多种配置,我也无法在一个实例中注册我的其他 ViewModel制作实例的方法 "reachable"

感谢您抽出宝贵时间,这是我认为与该问题相关的代码:

这是我的引导程序:

public class AppBootstrapper : BootstrapperBase
{
    private SimpleContainer _container = new SimpleContainer();

    public AppBootstrapper()
    {
        Initialize();

        var config = new TypeMappingConfiguration
        {
            DefaultSubNamespaceForViewModels = "ViewModel",
            DefaultSubNamespaceForViews = "View"
        };

        ViewLocator.ConfigureTypeMappings(config);
        Caliburn.Micro.ViewModelLocator.ConfigureTypeMappings(config);
    }

    protected override void Configure()
    {
        _container.Singleton<ShellViewModel, ShellViewModel>();
        _container.Singleton<IWindowManager, WindowManager>();
        //tried registering AboutViewModel in multiple ways
        _container.Singleton<AboutViewModel, AboutViewModel>();
        _container.RegisterSingleton(typeof(AboutViewModel), null,typeof(AboutViewModel));

        /
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        DisplayRootViewFor<ShellViewModel>();
    }


    protected override object GetInstance(Type service, string key)
    {
        var instance = _container.GetInstance(service, key);
        if (instance != null)
            return instance;
        throw new InvalidOperationException("Could not locate any instances.");
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return _container.GetAllInstances(service);
    }

    protected override void BuildUp(object instance)
    {
        _container.BuildUp(instance);
    }


}

ShellViewModel.cs:

public class ShellViewModel : Conductor<object>, IHandle<NavigationMessage>
{
    /// <summary>
    /// Caliburn.Micro event aggregator. (Publish/Subscribe pattern)
    /// </summary>
    public IEventAggregator events = new EventAggregator();
    public ShellViewModel()
    {
        //var aaa = IoC.Get<IEventAggregator>();
        events.Subscribe(this);
        ActivateItem(new AboutViewModel(events));
    }

    public void Handle(NavigationMessage message)
    {
        //var instance = IoC.GetInstance(message.ViewModelType,null);
        var instances = IoC.GetAllInstances(null);
        foreach(var i in instances)
        {

            MessageBox.Show(i.ToString());
        }
        ActivateItem(new AboutViewModel(events));

    }
}

和 AboutViewModel.cs:

/// <summary>
/// ViewModel belonging to the AboutView.xaml.
/// </summary>
/// <seealso cref="AboutView.xaml"/> 
public class AboutViewModel : Screen, IHandle<NavigationMessage>
{
    private readonly IEventAggregator _eventAggregator;
    /// <summary>
    /// Private container for the 'Version' public property.
    /// </summary>
    /// <see cref="Version"/>
    private string _version;

    /// <summary>
    /// Property containing a string of the application's current version (e.g.: 0.1.3.45)
    /// </summary>
    /// <see cref="_version"/> 
    [JsonIgnore]
    public string Version
    {
        get
        {
            return _version;
        }
        set
        {
            _version = value;
            NotifyOfPropertyChange(() => Version);
        }
    }

    /// <summary>
    /// Base constructor for the AboutViewModel class.
    /// </summary>
    public AboutViewModel(IEventAggregator eventAggregator)
    {         
        Logging.Info("Initialize AboutViewModel", this.GetType());
        Logging.Debug("Subscribing to the eventAggregator", this.GetType());
        _eventAggregator = eventAggregator;
        _eventAggregator.Subscribe(this);

        _version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
        Logging.Debug("Version loaded (" + _version + ")", this.GetType());
    }

    /// <summary>
    /// Boolean method connected to the ChatCommand activates or deactivates based on it's return
    /// </summary>
    /// <param name="obj">Object of type GotoPageMessage received from the messenger</param>
    public bool CanChat(object obj)
    {
        return true;
    }
    /// <summary>
    /// Method connected to the ChatCommand that sends the user to the 'Chat' view
    /// </summary>
    /// <param name="obj">Object of type GotoPageMessage received from the messenger</param>
    public void Chat(object obj)
    {

        _eventAggregator.PublishOnUIThread(new NavigationMessage(typeof(AboutViewModel)));
    }

    public void Handle(NavigationMessage message)
    {
        //This handle is used only to know how many instances I have active
        MessageBox.Show("about");
    }
}

编辑 1:

P.S.: 我以前的 ShellViewModel 是 Conductor.Collection.OneActive。仍然没有用。也许 AllActive 可以工作?...

覆盖 Caliburn Micro 的 SelectAssemblies 方法以定位所有视图:

protected override IEnumerable<Assembly> SelectAssemblies()
{
   return new[]
   {
       Assembly.GetExecutingAssembly(), typeof(MainViewModel).Assembly
   };
}

有关引导程序的更多信息 here

我现在确实找到了一个解决方案,没有弄乱程序集。

我注意到 ShellViewModel 的实例是可访问的,通过将实例保存到一个对象中并对其进行调试,我注意到我创建的所有 viewModel 实例都在 'Items'。

基本上这就是我在 ShellViewModel 内部的处理程序中所做的:

    public void Handle(NavigationMessage message)
    {
        ShellViewModel Shell = (ShellViewModel)IoC.GetInstance(typeof(ShellViewModel), null);
        object Instance = null;

        foreach (var item in Shell.Items)
        {
            if (item.ToString().Contains(message.ViewModelType.ToString()))
                Instance = item;
        }
        object AuxObject = new object();


        if (Instance == null)
        {
            try
            {
                Instance = Activator.CreateInstance(message.ViewModelType, Shell.events);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
        ActivateItem(Instance);

    }