我有一个使用Caliburn.Micro 2.0.1的wpf应用程序,我发现了Caliburn.Micro的奇怪行为。在最新的3.0.3中它也存在。
重现错误的超级简单项目:https://github.com/ihtfw/CaliburnMicroBug
MainWindowViewModel是屏幕导体。 有两个ScreenViewModel作为MainWindowViewModel的项目,其属性为SingletonViewModel。 在MainViewModel中,我可以切换到第一个ScreenViewModel或第二个。
除了在切换到第二个屏幕后仅在第二个ScreenViewModel上显示View for SingletonViewModel时,一切都很完美。
重现:
如何解决这个问题?
更新
使用ContentControl无法制作这些内容。应该使用显式视图。在这种情况下,SingletonView并设置它的DataContext。连接Caliburn.Micro操作绑定它们没有上下文。结果将是:
<local:SingletonView DataContext={Binding Path=SingletonViewModel} cal:Action.TargetWithoutContext="{Binding}" />
答案 0 :(得分:3)
如其他答案中所述,您不能拥有“单一视图”,xaml UI模型将不允许相同的UI元素在可视树中两次。
然而,您可以做的是将两个相同视图的实例绑定到视图模型。
要做到这一点,您需要回避框架的一个功能。
在内部,任何实现IViewAware
的视图模型都拥有对视图的弱引用,只要框架尝试定位视图模型的视图,它首先会查询该视图的视图模型。
如果返回引用,则视图将从其现有位置移除并插入新位置。
为了阻止这种情况,你可以做以下三件事之一:
SingletonViewModel
不会继承实施IViewAware
的内容,例如PropertyChangedBase
。ViewLocator.LocateForModel
以删除此行为。Hacky null out view
protected override void OnViewAttached(object view, object context)
{
Views[context ?? ViewAware.DefaultContext] = null;
}
删除IViewAware
行为
ViewLocator.LocatorForModel = (model, location, context) => ViewLocator.LocateForModelType(model.GetType(), location, context);
答案 1 :(得分:0)
我参与了您的项目,发现您的问题出在MainWindows构造函数中。改变MainWindow的构造函数如下:
public MainWindowViewModel()
{
Items.Add(new ScreenViewModel
{
DisplayName = "Screen 1",
SingletonViewModel = new SingletonViewModel()
});
Items.Add(new ScreenViewModel
{
DisplayName = "Screen 2",
SingletonViewModel = new SingletonViewModel()
});
ActiveItem = Items.First();
}
答案 2 :(得分:0)
这不是一个Bug。
UIElement
等UserControl
只能拥有一个逻辑父级。
您正在创建两个ScreenViews
,并且您尝试向这两个SingletonView
添加相同的SingletonView
,这是不可能的,因为class Car < ActiveRecord::Base
has_many :prices
end
class Price < ActiveRecord::Base
belongs_to :car
end
不能有两个父母。