出于某种原因,当尝试在Caliburn.Micro中使用设计时支持时,会出现IoC异常。
bei Caliburn.Micro.IoC。< .cctor> b__1(类型服务)bei Caliburn.Micro.ViewLocator。< .cctor> b__2(Type viewType)bei Caliburn.Micro.ViewLocator。< .cctor> b__9(TypeTypeType, DependencyObject displayLocation,Object context)bei Caliburn.Micro.ViewLocator。< .cctor> b__a(对象模型,DependencyObject displayLocation,Object context)bei Caliburn.Micro.View.OnModelChanged(DependencyObject targetLocation, DependencyPropertyChangedEventArgs args)bei System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)bei System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)bei System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)bei System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata元数据, EffectiveValueEntry oldEntry,EffectiveValueEntry& newEntry,布尔值 coerceWithDeferredReference,Boolean coerceWithCurrentValue, OperationType operationType)bei System.Windows.DependencyObject.InvalidateProperty(的DependencyProperty dp,Boolean preserveCurrentValue)bei System.Windows.Data.BindingExpressionBase.Invalidate(布尔 isASubPropertyChange)bei System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)bei System.Windows.Data.BindingExpression.Activate(Object item)bei System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt 尝试)bei System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(布尔 lastChance)bei MS.Internal.Data.DataBindEngine.Task.Run(布尔值 lastChance)bei MS.Internal.Data.DataBindEngine.Run(Object arg)
bei MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)bei System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()bei System.Windows.ContextLayoutManager.UpdateLayout()bei System.Windows.UIElement.UpdateLayout()
我希望为包含单个ContentControl的Window启用DesignTime支持,如文档here所示:
<Window x:Class="Test.MyShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:Test.DesignData.ViewModels"
mc:Ignorable="d"
ResizeMode="CanResizeWithGrip"
d:DataContext="{d:DesignInstance Type=viewModels:DesignShellViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True">
<ContentControl cal:View.Model="{Binding ActiveItem}" />
</Window>
在运行时使用以下ViewModel:
public class MyShellViewModel : ShellViewModel // derrived from own base class
{
public MyShellViewModel(IThemeManager themeManager)
: base(themeManager)
{
}
}
但是视图应该在命名空间DesignData中设计时绑定到此ViewModel:
public sealed class DesignShellViewModel : Conductor<IScreen>.Collection.OneActive
{
public DesignShellViewModel()
{
AssemblySource.Instance.Add(this.GetType().Assembly);
this.ActivateItem(new TestViewModel());
}
}
这是一个包含单个屏幕的简单导体(TestViewModel) 在Test.DesignData命名空间中:
public class TestViewModel : Screen
{
// nothing interesting to see here
}
和相应的观点
<UserControl x:Class="Test.DesignData.Views.TestView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">It's working at design time!</TextBlock>
</Grid>
</UserControl>
有谁知道问题可能是什么?
编辑:mvermef的帖子让我更接近解决方案(我认为)
现在出现一条消息,Caliburn无法找到ViewModel的视图(就像它在运行时一样,当名称错误或类未找到/缺失时......但是它存在于同一个库中)。
以下是@mvermef提出的 Bootstrapper 的一部分:
// nothing special here, is empty... just a concrete class to create it via Xaml
public class Bootstrapper : Bootstrapper<IShell>
{
}
// contains the important parts (Autofac, MEF integration etc.)
public class Bootstrapper<TViewModel> : BootstrapperBase
{
// I use Common.Logging
private static readonly ILog Log = LogManager.GetLogger(typeof(Bootstrapper<TViewModel>));
// the Autofac container
private IContainer container;
static Bootstrapper()
{
// Redirect the default log output of Caliburn and use Common.Logging instead
Caliburn.Micro.LogManager.GetLog = type => new CommonLoggingAdapter(type);
}
protected Bootstrapper()
{
this.Initialize();
}
protected override void Configure()
{
var builder = new ContainerBuilder();
var catalogs = new List<ComposablePartCatalog>();
// Register basic services required by Caliburn
builder.RegisterType<WindowManager>()
.As<IWindowManager>()
.InstancePerLifetimeScope();
builder.RegisterType<EventAggregator>()
.As<IEventAggregator>()
.InstancePerLifetimeScope();
if (Execute.InDesignMode)
{
// code that follows next should not execute in Design Mode, so I jump over (thanks to mvermev, the Exception is gone because of this => but still the problem with the missing View)
return;
}
...
}
protected TInstance Get<TInstance>(string key = null)
{
return (TInstance)this.GetInstance(typeof(TInstance), key);
}
protected override object GetInstance(Type service, string key)
{
if (Execute.InDesignMode)
{
return base.GetInstance(service, key);
}
return string.IsNullOrWhiteSpace(key)
? this.container.Resolve(service)
: this.container.ResolveNamed(key, service);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return Execute.InDesignMode
? base.GetAllInstances(service)
: this.container.Resolve(typeof(IEnumerable<>).MakeGenericType(service)) as IEnumerable<object>;
}
protected override void BuildUp(object instance)
{
if (Execute.InDesignMode)
{
base.BuildUp(instance);
}
else
{
this.container.InjectProperties(instance);
}
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
this.DisplayRootViewFor<TViewModel>();
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
foreach (var assembly in base.SelectAssemblies())
{
yield return assembly;
}
yield return Assembly.GetEntryAssembly();
yield return typeof(TViewModel).Assembly;
}
// other methods are only executed at runtime / not design time relevant
}
编辑2:已解决!需要将DesignTime视图程序集添加到Boostrapper的SelectAssemblies方法中。 Bootstrapper和Views不在同一个程序集中(在我的例子中)。
protected override IEnumerable<Assembly> SelectAssemblies()
{
foreach (var assembly in base.SelectAssemblies())
{
yield return assembly;
}
yield return typeof(MyDesignTimeView).Assembly; // !!!IMPORTANT!!!
yield return Assembly.GetEntryAssembly();
yield return typeof(TViewModel).Assembly;
}
答案 0 :(得分:1)
您是否使用Override for SelectedAssemblies,这就是Caliburn如何找到您需要的其他项目(如视图/视图模型),而不管是否为引用的程序集,尤其是在您使用MEF作为容器时。 -