我一直在尝试将Caliburn.Micro MVVM框架集成到C#WPF项目中,我处于中间位置。
我目前只有三种视图模型:
目前我正在尝试在AboutView上使用一个绑定到' Chat()'在AboutViewModel上的方法,应该将用户带到ChatView,但我正在使用AboutViewModel进行测试。 (如处理程序所示)
我需要的是所有的Screen / ViewModel都是Singleton并且只有一个实例,当我尝试更改页面时,它会返回已经存在的页面。
这里的问题是我在IoC.GetAllInstances(),ShellViewModel中只注册了一个实例,即使我在引导程序中尝试了多个配置,我也无法以某种方式注册我的其他ViewModel使他们的实例"可达"
我感谢您的时间,以下是我认为与此问题相关的代码:
这是我的引导程序:
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可能有用吗?...
答案 0 :(得分:1)
重写用于caliburn micro的SelectAssemblies方法以查找所有视图:
protected override IEnumerable<Assembly> SelectAssemblies()
{
return new[]
{
Assembly.GetExecutingAssembly(), typeof(MainViewModel).Assembly
};
}
更多关于引导程序here。
答案 1 :(得分:0)
我实际上现在找到了一个解决方案,而没有弄乱Assemblies。
我注意到ShellViewModel的实例是可访问的,通过将实例保存到对象并进行调试,我注意到我创建的所有viewModel实例都在&#39; Items&#39;中。
基本上这就是我在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);
}