2014-12-15 4 views
14

Ich verwende PRISM 5 in meiner WPF-Anwendung. Und die Shell-Ansicht in meiner Anwendung hat zwei Regionen, betrachte sie als A und B. Die Region A enthält ein POPUP (die PRISM 5-Interaktivitätsfunktion wird verwendet, um ein Popup anzuzeigen).IOC-Container in einem Popup abrufen

Die Anwendung funktioniert, wenn ich eine Instanz des Popup-View-Modells im Konstruktor der Ansicht erstellen.

Arbeits Code

public PopupView() 
{ 
    InitializeComponent(); 
    this.DataContext = new PopupViewModel(); // Working code 
} 

Aber wenn ich versuche Ansicht Modellinstanz mit der Abhängigkeit Injektion Anwendung nicht auf den InitializeComponent(); der übergeordneten Ansicht (Ansicht A) zu erstellen.

DI Problem Code

public PopupView(PopupViewModel viewModel) 
{ 
    InitializeComponent(); // Failing in AView initialze 
          // before reaching here 

    this.DataContext = viewModel; 
} 

anzeigen Mustereintragung in Modul/Bootstrap

container.RegisterType<AViewModel>(); 

Fehler

Nullreference Ausnahme aufgetreten aufgetreten

Stacktrace (Herausgegeben für die Frage)

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 (ein Edited projektspezifische Informationen zu vermeiden)

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) 
     { 
     } 
} 
+1

"Die Anwendung versagt", was das bedeutet? Hast du eine Ausnahme? – Console

+0

Können Sie bitte den Code posten, der das angezeigte Popup aufruft? – Console

+0

In StackTrace wird Unity nicht verwendet. Es kann AView mit keinem Standardkonstruktor erstellen. Sie können InitializeComponent nicht zum Auflösen von Komponenten aus dem Unity-Container verwenden. – norekhov

Antwort

0

glaube ich Ihnen die AViewModel registrieren, aber IoC Container hat nicht die richtige Instanz oder Fabrik für PopupViewModel. Aus meiner Sicht benötigt Ihre Ansicht PopupViewModel als eine Abhängigkeit, aber der Container kann es nicht auflösen, weil dieser Typ nicht registriert ist.

Zusätzlich drücken Sie bitte hier Ihre XAML-Datei, weil die Ausnahme von InitializeComponent() -Methode ausgelöst wurde, geschieht es, weil inkonsistente Markup. Daher müssen wir das Markup sehen, um Ihnen mehr Feedback zu geben.

+0

Erraten, dass Einheit verwendet wird. In Unity müssen Typen nicht registriert werden, um aufgelöst zu werden. Nur Schnittstellen und wenn der Konstruktor nicht eindeutig ist oder wenn ein anderer Lifetime Manager gewünscht wird. – Michael

1

Ich nehme an, dass Sie InteractionRequestTrigger mit PopupWindowAction in Ihrem XAML verwenden, um PopupView an entsprechende InteractionRequest zu binden.

Sie können PopupViewModel nicht an den Konstruktor der PopupView übergeben, da die Ansicht direkt von PopupWindowAction erstellt wird und nicht von DI-Container. Wenn PopupWindowActionPopupView erstellt, wird die DataContext der Ansicht auf das Objekt INotification gesetzt, das Sie an die InteractionRequest.Raise(…) übergeben haben. Das INotification verfügt über eine Content Eigenschaft, die verwendet werden kann, um alle gewünschten Daten an die PopupView zu übergeben. Zum Beispiel können Sie hier PopupViewModel übergeben.

EDIT: Ich habe PopupWindowActionsources nachgeschlagen und es scheint, dass ich falsch liege.Sie verwenden ServiceLocator wenn sie versuchen, PopupWindowAction.WindowContentType zu instanziiert, so technisch PopupViewModel zu PopupView ‚s Konstruktor sollte in Ausnahmefällen nicht zur Folge haben, aber es ist immer noch nutzlos, da nach Ansicht der DataContext weiter durch das INotification zum InteractionRequest gebene Objekt ersetzt wird.

Beispiel:

// 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)))); 
    } 
} 
Verwandte Themen