我在WPF应用程序中使用PRISM 5。我的应用程序中的Shell View 有两个区域,将其视为A和B。区域A包含一个POPUP(PRISM 5交互功能用于显示弹出窗口)。
当我在 View 的构造函数中创建弹出 View 模型的实例时,该应用程序正在运行。
工作代码
public PopupView()
{
InitializeComponent();
this.DataContext = new PopupViewModel(); // Working code
}
但是当我尝试使用依赖注入(inject)创建 View 模型实例时,应用程序在父 View ( View A)的
InitializeComponent();
上失败。DI不起作用代码
public PopupView(PopupViewModel viewModel)
{
InitializeComponent(); // Failing in AView initialze
// before reaching here
this.DataContext = viewModel;
}
在模块/ bootstrap 中查看模型注册
container.RegisterType<AViewModel>();
发生错误
发生NULLReference异常
Stacktrace (针对问题进行编辑)
at System.DefaultBinder.BindToMethod(BindingFlags bindingAttr, MethodBase[] match, Object[]& args, ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, Object& state)
at MS.Internal.Xaml.Runtime.DynamicMethodRuntime.CreateInstanceWithCtor(Type type, Object[] args)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(XamlType xamlType, Object[] args)
at MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.CreateInstance(XamlType xamlType, Object[] args)
at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.WriteEndObject()
at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at MyNamespace.AView.InitializeComponent() in e:\xxx\xxxxx\xxx\AView.xaml:line 1
at MyNamespace.AView..ctor(AViewModel viewModel) in e:\xxx\xxxxx\xxx\AView.xaml.cs:line 18
AViewModel (为了避免特定于项目的信息而编辑)
public class ItemSelectionNotification : Confirmation
{
//This class includes properties related to my project
}
public class AViewModel
{
public InteractionRequest<ItemSelectionNotification> ItemSelectionRequest { get; private set; }
public AViewModel(EventAggregator eventAggregator,IUnityContainer container)
{
this.eventAggregator = eventAggregator;
this.container = container;
ItemSelectionRequest = new InteractionRequest<ItemSelectionNotification>();
SettingsCommand = new DelegateCommand(OnClickSetting); //Command for settings button click
}
//Button click handling
public void OnClickSetting()
{
var notification = new ItemSelectionNotification()
{
Title = "Items"
};
this.ItemSelectionRequest.Raise(notification,OnSaveCallback);
}
private void OnSaveCallback(PropertySelectionNotification returned)
{
}
}
最佳答案
我将假设您在XAML中将InteractionRequestTrigger
与PopupWindowAction
结合使用,以将PopupView
绑定(bind)到相应的InteractionRequest
。
您不能将PopupViewModel
传递给PopupView
的构造函数,因为 View 是由PopupWindowAction
直接创建的,而不是由DI容器创建的。当PopupWindowAction
创建PopupView
时,它将 View 的DataContext
设置为您传递给INotification
的InteractionRequest.Raise(…)
对象。该INotification
具有Content
属性,可用于将所需的任何数据传递给PopupView
。例如,您可以在此处传递PopupViewModel
。
编辑:我查了PopupWindowAction
sources,看来我错了。他们在尝试实例化ServiceLocator
时会使用PopupWindowAction.WindowContentType
,因此从技术上讲,将PopupViewModel
传递给PopupView
的构造函数不应导致异常,但由于将 View 的DataContext
进一步替换为传递给INotification
的InteractionRequest
对象,因此它仍然没有用。
例:
// PopupViewModel.cs
internal sealed class PopupViewModel
{
public PopupViewModel(string message)
{
Message = message;
}
public string Message { get; }
}
// PopupView.xaml
<UserControl …>
<Grid DataContext="{Binding Content, Mode=OneTime}">
<Label Text="{Binding Message, Mode=OneTime}" />
</Grid>
</UserControl>
// SomeViewModel.cs
internal sealed class SomeViewModel
{
// Don't use DI-container references to construct objects, inject factories instead.
// Also to keep things simple you can just create your PopupViewModel directly if it has no external dependencies.
private readonly Func<string, PopupViewModel> _popupViewModelFactory;
public SomeViewModel(Func<string, PopupViewModel> popupViewModelFactory)
{
_popupViewModelFactory = popupViewModelFactory;
}
public ICommand ShowPopupCommand { get; } = new DelegateCommand(DoShowPopup);
public InteractionRequest<INotification> PopupRequest { get; } = new InteractionRequest<INotification>();
private void DoShowPopup()
{
PopupRequest.Raise(new Notification
{
Content = _popupViewModelFactory("This is a Popup Message!")
}, _ =>
{
// Callback code.
});
}
}
// SomeView.xaml
<UserControl …>
<i:Interaction.Triggers>
<prism:InteractionRequestTrigger SourceObject="{Binding PopupRequest, Mode=OneTime}">
<prism:PopupWindowAction WindowContentType="views:PopupView" />
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
<Button Command="{Binding ShowPopupCommand, Mode=OneTime}" />
<UserControl>
// SomeModule.cs (or maybe Bootstrapper.cs if you setup your container in Bootstrapper)
public sealed class SomeModule : IModule
{
private readonly IUnityContainer _container;
public SomeModule(IUnityContainer container)
{
_container = container;
}
public override void Initialize()
{
_container.RegisterType<Func<string, PopupViewModel>>(
new InjectionFactory(c =>
new Func<string, PopupViewModel>(message =>
c.Resolve<PopupViewModel>(
new ParameterOverride("message", message))));
}
}
关于c# - 在弹出窗口中获取IOC容器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27485492/