- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
Here Caliburn.Micro成功与ModernUI结合。
但是,如果要使用多个窗口,则还需要重新实现Caliburn的WindowManager
以与ModernUI一起正常使用。怎么做到呢?
更新:
(有关IoC容器/依赖项注入的其他问题)
好的,我知道了:我在这里使用了构造函数注入:
public class BuildingsViewModel : Conductor<IScreen>
{
public BuildingsViewModel(IWindowManager _windowManager)
{
windowManager = _windowManager;
}
}
BuildingsViewModel
而言,
ModernWindowManager
接口的
IWindowManager
实现,因为
Bootstrapper
的
Configure()
方法中的这一行:
container.Singleton<IWindowManager, ModernWindowManager>();
_windowManager.ShowWindow(new PopupViewModel());
ModernWindowViewModel
中,该实例首先从容器中解析吗?
SimpleContainer
,还是最好使用成熟的框架,如Castle Windsor?我应该避免混合吗?
Main()
方法中),然后所有对象实例必须从其注入的依赖项中成长出来?
最佳答案
只需创建自己的派生WindowManager
并覆盖EnsureWindow
:
public class ModernWindowManager : WindowManager
{
protected override Window EnsureWindow(object rootModel, object view, bool isDialog)
{
var window = view as ModernWindow;
if (window == null)
{
window = new ModernWindow();
window.SetValue(View.IsGeneratedProperty, true);
}
return window;
}
}
ModernWindow
,并且必须使用
LinkGroupCollection
或必须设置窗口的
ContentSource
属性,否则将没有任何内容。
View-First
,但使用上面的方法,它可以工作
ViewModel-First
。
PopupView
我做了以下
<mui:ModernWindow x:Class="TestModernUI.ViewModels.PopupView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mui="http://firstfloorsoftware.com/ModernUI"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" ContentSource="/ViewModels/ChildView.xaml">
</mui:ModernWindow>
public class PopupViewModel : Screen
{
// Blah
}
public void SomeMethod()
{
_windowManager.ShowWindow(new PopupViewModel()); // Or use injection etc
}
ModernWindowManager
代替
WindowManager
!
container.Singleton<IWindowManager, ModernWindowManager>();
ModernWindow
中,因此每个弹出窗口都必须有两个
UserControls
!
EnsureWindow
中的
ModernWindowManager
,以便它基于
UserControl
创建一个
ModernWindow
并将
ContentSource
设置为要加载的视图的URI,这将触发内容加载器和连接您的
ViewModel
。如果有时间尝试,我会进行更新。
protected override Window EnsureWindow(object rootModel, object view, bool isDialog)
{
var window = view as ModernWindow;
if (window == null)
{
window = new ModernWindow();
// Get the namespace of the view control
var t = view.GetType();
var ns = t.Namespace;
// Subtract the project namespace from the start of the full namespace
ns = ns.Remove(0, 12);
// Replace the dots with slashes and add the view name and .xaml
ns = ns.Replace(".", "/") + "/" + t.Name + ".xaml";
// Set the content source to the Uri you've made
window.ContentSource = new Uri(ns, UriKind.Relative);
window.SetValue(View.IsGeneratedProperty, true);
}
return window;
}
TestModernUI.ViewModels.PopupView
,生成的URI是
/ViewModels/PopupView.xaml
,然后通过内容加载器自动加载和绑定。
Bootstrapper
配置方法:
protected override void Configure()
{
container = new SimpleContainer();
container.Singleton<IWindowManager, ModernWindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<ChildViewModel>();
container.PerRequest<ModernWindowViewModel>();
container.PerRequest<IShell, ModernWindowViewModel>();
}
WindowManager
和
EventAggregator
之类的CM服务均已针对它们各自的接口注册为单例,因此在运行时每个实例只有1个实例可用。
PerRequest
,每次您从容器中请求一个实例时,该实例都会创建一个新实例-这样,您可以多次弹出相同的窗口,而不会出现奇怪的行为!
1) So now I wonder how can I replace this line using an injection(with interface)? _windowManager.ShowWindow(new PopupViewModel());
PopupViewModel
具有多个依赖项,则可以将其注入到父类中,但这会将父视图模型以某种方式耦合到
PopupViewModel
。
PopupViewModel
的实例。
PopupViewModel
注册为
PerRequest
,则每次请求时都会得到一个新实例。如果在视图模型中只需要一个弹出实例,则可以将其注入:
public class MyViewModel
{
private PopupViewModel _popup;
private IWindowManager _windowManager;
public MyViewModel(PopupViewModel popup, IWindowManager windowManager)
{
_popup = popup;
_windowManager = windowManager;
}
public void ShowPopup()
{
_windowManager.ShowPopup(_popup);
}
}
PopupViewModel
实例。
IoC.Get<T>
。
IoC
是静态类,可让您在实例化后访问DI容器
public void ShowPopup()
{
var popup = IoC.Get<PopupViewModel>();
_windowManager.ShowWindow(popup);
}
IoC
方法的任何调用委派给了该容器-
IoC.Get<T>
调用了引导程序的
GetInstance
和其他方法:
public class AppBootstrapper : BootstrapperBase {
SimpleContainer container;
public AppBootstrapper() {
Initialize();
}
protected override void Configure() {
container = new SimpleContainer();
container.Singleton<IWindowManager, ModernWindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<IShell, ModernWindowViewModel>();
// Register viewmodels etc here....
}
// IoC.Get<T> or IoC.GetInstance(Type type, string key) ....
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.");
}
// IoC.GetAll<T> or IoC.GetAllInstances(Type type) ....
protected override IEnumerable<object> GetAllInstances(Type service) {
return container.GetAllInstances(service);
}
// IoC.BuildUp(object obj) ....
protected override void BuildUp(object instance) {
container.BuildUp(instance);
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) {
DisplayRootViewFor<IShell>();
}
Resolve
和
Release
您的组件并更明确地管理它们的生命周期,但是我在这里不做介绍
2) If I want my whole project match DI pattern, all objects instances must be injected into ModernWindowViewModel, that resolves from container first?
ModernWindowViewModel
所需的依赖项。儿童需要的任何东西都会自动解决并注入,例如:
public class ParentViewModel
{
private ChildViewModel _child;
public ParentViewModel(ChildViewModel child)
{
_child = child;
}
}
public class ChildViewModel
{
private IWindowManager _windowManager;
private IEventAggregator _eventAggregator;
public ChildViewModel(IWindowManager windowManager, IEventAggregator eventAggregator)
{
_windowManager = windowManager;
_eventAggregator = eventAggregator;
}
}
ParentViewModel
-
ChildViewModel
将获取其所有依赖项。您无需将它们注入父级。
3) Is it okay to use Caliburn's SimpleContainer for whole project, or better use mature framework like Castle Windsor? Should I avoid mixing?
SimpleContainer
很好-温莎城堡具有更多功能,但是您可能永远不需要它们(我只使用了一些高级功能)
4) Integrating an IoC container into an existing application requires creating this container first(in Main() method of console app for example), and then all object instanses must grow from it with injected dependencies?
// The bootstrapper sets up the container/engine etc
public class Bootstrapper
{
// Castle Windsor Container
private readonly IWindsorContainer _container;
// Service for writing to logs
private readonly ILogService _logService;
// Bootstrap the service
public Bootstrapper()
{
_container = new WindsorContainer();
// Some Castle Windsor features:
// Add a subresolver for collections, we want all queues to be resolved generically
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel));
// Add the typed factory facility and wcf facility
_container.AddFacility<TypedFactoryFacility>();
_container.AddFacility<WcfFacility>();
// Winsor uses Installers for registering components
// Install the core dependencies
_container.Install(FromAssembly.This());
// Windsor supports plugins by looking in directories for assemblies which is a nice feature - I use that here:
// Install any plugins from the plugins directory
_container.Install(FromAssembly.InDirectory(new AssemblyFilter("plugins", "*.dll")));
_logService = _container.Resolve<ILogService>();
}
/// <summary>
/// Gets the engine instance after initialisation or returns null if initialisation failed
/// </summary>
/// <returns>The active engine instance</returns>
public IIntegrationEngine GetEngine()
{
try
{
return _container.Resolve<IIntegrationEngine>();
}
catch (Exception ex)
{
_logService.Fatal(new Exception("The engine failed to initialise", ex));
}
return null;
}
// Get an instance of the container (for debugging)
public IWindsorContainer GetContainer()
{
return _container;
}
}
GetEngine
的调用通过从创建完整依赖关系树的容器中解析
Engine
来启动应用程序。
public partial class IntegrationService : ServiceBase
{
private readonly Bootstrapper _bootstrapper;
private IIntegrationEngine _engine;
public IntegrationService()
{
InitializeComponent();
_bootstrapper = new Bootstrapper();
}
protected override void OnStart(string[] args)
{
// Resolve the engine which resolves all dependencies
_engine = _bootstrapper.GetEngine();
if (_engine == null)
Stop();
else
_engine.Start();
}
protected override void OnStop()
{
if (_engine != null)
_engine.Stop();
}
}
public class ConsoleAppExample
{
private readonly Bootstrapper _bootstrapper;
private IIntegrationEngine _engine;
public ConsoleAppExample()
{
_bootstrapper = new Bootstrapper();
// Resolve the engine which resolves all dependencies
_engine = _bootstrapper.GetEngine();
_engine.Start();
}
}
public class IntegrationEngine : IIntegrationEngine
{
private readonly IScheduler _scheduler;
private readonly ICommsService _commsService;
private readonly IEngineStateService _engineState;
private readonly IEnumerable<IEngineComponent> _components;
private readonly ConfigurationManager _configurationManager;
private readonly ILogService _logService;
public IntegrationEngine(ICommsService commsService, IEngineStateService engineState, IEnumerable<IEngineComponent> components,
ConfigurationManager configurationManager, ILogService logService)
{
_commsService = commsService;
_engineState = engineState;
_components = components;
_configurationManager = configurationManager;
_logService = logService;
// The comms service needs to be running all the time, so start that up
commsService.Start();
}
IntegrationEngine
-它们由容器处理
关于c# - 使用ModernUI + Caliburn.Micro组合重新实现WindowManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29079328/
我使用 WindowManager 添加了一个 View 。 它正确地显示了我想做的事情, 但我有一个问题。 这就是问题。 后退键不影响在android组件下(如事件) 我想要的是我添加的 View
I have drawn an overlay using WindowManager. it's width and height are WindowManager.LayoutParams.MA
我正在开发一个锁屏应用程序,我在服务中使用 WindowManager 添加一个 View 。我已经在 list 文件中为所有 Activity 设置了 Orientation PORTRAIT,但这
我在服务中有一个 WindowManger,我添加了一些标志: params = new WindowManager.LayoutParams( WindowManager.LayoutPar
这是我的代码: params = new WindowManager.LayoutParams( WindowManager.LayoutParams.FLAG_FULLSCREEN,
出于某种原因,我不断收到错误膨胀类消息,因为我正在尝试实现 引起:java.lang.NullPointerException 在 pap.crowslanding.GameView.(GameVie
我正在将 WPF 与当前最新、最好的版本 Caliburn.Micro (1.4.1) 一起使用。我用IWindowManager.ShowWindow(...)打开一个新的无模式窗口: privat
我正在尝试使用 WindowManager 覆盖屏幕,它运行良好,但覆盖屏幕不会覆盖页脚,而是覆盖标题。 这是我的代码。 wm = (WindowManager) getSystemService(C
我使用 wordpress,目前正在为 tinymce-editor 编写一个插件。我使用 windowmanager.open() 函数来显示一个模态,但是我不知道如何在这个模态中隐藏 ok 按钮。
我正在使用此代码通过调暗来更改 Activity 的亮度。 WindowManager.LayoutParams layoutParameters = getWindow().getAttribute
我对由 windowmanager 提供支持的 float 窗口有疑问。它停在屏幕边界处,但我希望它通过。 void startF(int x, int y) { removePopup();
我正在尝试使用 windowManager.open({...}) 创建一个模态窗口,它将有一个(可能很长)项目列表。确保它正确显示的唯一方法是将固定高度设置为模态并使其内容可滚动。 Document
WindowManager.removeViewImmediate() 的文档包含警告(强调我的): Special variation of ViewManager.removeView(View)
我有一个服务。我已经使用 WindowManager 在服务运行期间显示一些 UI。此外,我在此服务的生命周期内显示通知。 下面是我的服务类 public class DemoService exte
我(我希望)在为 Google TV 进行一些开发时遇到了一些小问题 我想要做的是我希望能够在右下角显示一个小窗口,这很好..问题是我不确定如何摆脱后台的屏幕保护程序 这是我目前的代码。 pu
显示在屏幕上的窗口 public class FlatingViewService extends Service{ public static WindowManager windowM
我已经针对同一问题查找了几个帖子,但似乎无法解决我的问题。我在整个应用程序中都使用了微调器,它们运行良好。当我尝试在弹出窗口中使用微调器时,选择它时出现错误。弹出窗口用于添加引用,我已经声明了一个全局
我的应用程序在特定时间向用户显示一个按钮作为 TYPE_SYSTEM_ALERT,我试图让用户 move 它。触摸和 move Action 确实使用以下代码注册,但按钮不会 move 。我错过了什么
有人可以在下面详细解释一下吗, 1- What is the use of ActivityManager & WindowManager? 2- What is the difference bet
我正在开发用于背景视频录制 的应用程序,这就是我使用 WindowManager 的原因,但它对我不起作用。出现以下错误: 08-23 15:38:21.021: E/AndroidRuntime(4
我是一名优秀的程序员,十分优秀!