2016-02-15 3 views
7

Hintergrund

Hallo alle SO Zuschauer. Ich bin normalerweise ein Android-Entwickler, aber jetzt entwickle ich eine Cross-Plattform-Anwendung für WPF und Android. Davon abgesehen gibt es praktisch keine Informationen darüber, wie ich direkt machen kann, was ich will. Also habe ich eine dreiteilige Blog-Serie gefunden, die sich mit der Entwicklung eines Windows-basierten plattformübergreifenden MVVM-Projekts beschäftigt. Solange ich die PCL so eingestellt habe, dass sie mit Xamarin.Android kompatibel ist, sollte jeder Code, der keinen Fehler verursacht, funktionieren, sobald ich auf die Android-Seite der Dinge komme. Hier sind die Links zu den Blog-Posts: Blog 1, Blog 2, Blog 3. Wieder mache ich Android, also bin ich neu im Codieren für eine WPF-Anwendung.MVVM Licht - PCL + WPF - Erste Ausnahme des Typs Microsoft.Practices.ServiceLocation.ActivationException

Ausgabe

Also heute mein Problem nur mit der PCL-WPF Seite zu tun ist, die mit dem oben verlinkten Blogeintrag bezieht. Ich habe jeden einzelnen Schritt in den Posts so gut wie möglich verfolgt. Der Blog verwendet WinRT und WinPhone als die beiden Zielplattformen, daher musste ich selbst versuchen, Dinge herauszufinden, damit die Dinge auf dem WPF funktionieren. Zwei der Dinge, die ich tun musste, war IsolatedStorage und grundsätzlich das WinPhone App.Xaml zu verwenden, um die WPF-Seite aufzubauen.

Ich habe den Blog den ganzen Weg bis zum Ende fertig und Build gelingt. Ich kann sogar mein Beispiel für Debug-Zeilen sehen, wie es am Ende des dritten Blogposts heißt. Allerdings, wenn ich es laufen gehen, erhalte ich folgendes:

Activation wurde nicht behandelt durch Benutzercode

Eine Ausnahme vom Typ ‚Microsoft.Practices.ServiceLocation.ActivationException‘ aufgetreten in GalaSoft.MvvmLight.Extras .dll wurde aber nicht im Benutzercode behandelt

$ exception {Microsoft.Practices.ServiceLocation.ActivationException: Typ nicht im Cache gefunden: StackOverF.Services.IStorageService. bei GalaSoft.MvvmLight.Ioc.SimpleIoc.DoGetService (Typ serviceType, String-Schlüssel, boolescher Cache) in c: \ MvvmLight \ Quelle \ GalaSoft.MvvmLight \ GalaSoft.MvvmLight.Extras (PCL) \ Ioc \ SimpleIoc.cs: Zeile 537 bei GalaSoft.MvvmLight.Ioc.SimpleIoc.GetService (Typ serviceType) in C: \ MvvmLight \ Quelle \ GalaSoft.MvvmLight \ GalaSoft.MvvmLight.Extras (PCL) \ Ioc \ SimpleIoc.cs: Zeile 789 bei GalaSoft.MvvmLight. Ioc.SimpleIoc.MakeInstanceTClass in C: \ MvvmLight \ Source \ GalaSoft.MvvmLight \ GalaSoft.MvvmLight.Extras (PCL) \ Ioc \ SimpleIoc.cs: Linie 729} System.Exception {

} Microsoft.Practices.ServiceLocation.ActivationException

Gibt es irgendetwas, dass Sie mir sagen können, dass vielleicht der Blogautor übersprungen hat, dass ich tun muss? Vielleicht, wenn genug Felsen an diesem geworfen werden „Findling“, werde es offen knacken ...

Klärung

Grundsätzlich gibt es derzeit nur zwei Projekte in meine Visual Studio-Lösung. Einer ist die Portable Class Library. Die andere ist die WPF-Anwendung. In naher Zukunft, sobald ich Dinge auf der WPF-Seite der Gleichung arbeiten, werde ich die PCL in Xamarin verwenden, um den Code in einem Android-Projekt wiederzuverwenden. Allerdings ist die Android-Seite nicht Teil meines Problems hier. Ich habe das obige Problem, wenn ich nur mit dem WPF-Projekt zu tun habe.

-Code (zuletzt 18. Februar bearbeitet, 2016)

IMainViewModel.cs

using GalaSoft.MvvmLight.Command; 
using StackOverF.Models; 
using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace StackOverF.ViewModels { 
    public interface IMainViewModel { 
     ObservableCollection<Workload> Workload { get; } 

     RelayCommand RefreshCommand { get; } 
     RelayCommand AddCommand { get; } 
    } 
} 

MainViewModel.cs

using GalaSoft.MvvmLight; 
using GalaSoft.MvvmLight.Command; 
using StackOverF.Models; 
using StackOverF.Services; 
using System; 
using System.Collections.ObjectModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 


namespace StackOverF.ViewModels { 
    public class MainViewModel : ViewModelBase,IMainViewModel { 

     private IDataService dataService; 

     public MainViewModel(IDataService dataService) { 
      this.dataService = dataService; 

      RefreshAsync(); 
     } 

     private ObservableCollection<Workload> workload = new ObservableCollection<Workload>(); 
     public ObservableCollection<Workload> Workload { 
      get { 
       return workload; 
      } 
     } 

     #region Commands 

     #region Refresh 
     private RelayCommand refreshCommand; 
     public RelayCommand RefreshCommand { 
      get { 
       return refreshCommand ?? (refreshCommand = new RelayCommand(async() => { await RefreshAsync();})); 
      } 
     } 

     private async Task RefreshAsync() { 
      workload.Clear(); 
      foreach (Workload listing in await dataService.GetWorkloadAsync()) { 
       workload.Add(listing); 
      } 
     } 
     #endregion 

     #region Add 
     private RelayCommand addCommand; 
     public RelayCommand AddCommand { 
      get { 
       return addCommand ?? 
        (addCommand = new RelayCommand(async() => { 
         Workload listing = new Workload() { Id = 3, Serial = "relay12" }; 
         await dataService.AddWorkloadAsync(listing); 
         workload.Add(listing); 
        })); 
      } 
     } 
     #endregion 

     #endregion 
    } 
} 

LocatorService.cs (DeviceLocatorService, in WPF-Projekt)

using GalaSoft.MvvmLight; 
using GalaSoft.MvvmLight.Ioc; 
using Microsoft.Practices.ServiceLocation; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace StackOverF.Services { 
    public class DeviceLocatorService { 
     static DeviceLocatorService() { 
      ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

      if (ViewModelBase.IsInDesignModeStatic) { 
      } 
      else { 
      } 

      if (!SimpleIoc.Default.IsRegistered<IStorageService>()) 
       SimpleIoc.Default.Register<IStorageService, StorageService>(); 
     } 

     public static void Cleanup() { 
     } 
    } 
} 

LocatorService.cs (LocatorService, in PCL-Projekt)

using Microsoft.Practices.ServiceLocation; 
using GalaSoft.MvvmLight; 
using GalaSoft.MvvmLight.Ioc; 
using StackOverF.ViewModels; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace StackOverF.Services { 
    public class LocatorService { 
     static LocatorService() { 
      ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 


      // Services 
      if (ViewModelBase.IsInDesignModeStatic) { 
       SimpleIoc.Default.Register<IDataService, Design.DataService>(); 
      } 
      else { 
       SimpleIoc.Default.Register<IDataService, Services.DataService>(); 
      } 

      // View Models 
      SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(); 
     } 

     public IMainViewModel MainViewModel { 
      get { 
       return ServiceLocator.Current.GetInstance<IMainViewModel>(); 
      } 
     } 

     public static void Cleanup() { 
     } 
    } 
} 

Es Fehler (NUR bei der DEBUGGING) auf der return ServiceLocator.Current.GetInstance<IMainViewModel>(); Linie.

App.xaml

<Application x:Class="StackOverF.App" 
      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" 
      xmlns:services="clr-namespace:StackOverF.Services;assembly=StackOverF.PCL" 
      xmlns:deviceServices="clr-namespace:StackOverF.Services" 
      StartupUri="Views/MainWindow.xaml"> 
    <Application.Resources> 
     <ResourceDictionary> 
      <deviceServices:DeviceLocatorService x:Key="Locator.WPF" d:IsDataSource="True" /> 
      <services:LocatorService x:Key="Locator" d:IsDataSource="True" /> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 
+0

WPF für Windows? Ich verstehe nicht wirklich, auf welche Plattform Sie abzielen. – sexta13

+0

Es ist Cross-Plattform. Die TWO-Plattformen, für die ich arbeite, sind WPF für Windows und Android für ... Android lol. Sie haben einen "universellen" Code in der PCL, der auf beiden Plattformen geteilt werden kann, während plattformspezifischer Code in eigenen Projekten verwendet wird. –

+0

@Steven_BDawg Können Sie Ihren DeviceLocatorService anzeigen? Wie ich finde, IStorageService ist nicht in IoC-Container registriert. – Valentin

Antwort

1

Die Lösung für mein Problem ist einfacher als man erwarten könnte. WPF Anwendungen haben kein Problem mit MVVM Toolkits/Frameworks, aber sie scheinen ein Problem mit der Freigabe zu haben. Da WPF keine plattformübergreifende Sprache sein sollte, wird die "richtige" Art, so etwas zu programmieren, nicht funktionieren.

Das Problem versucht, kommt um beiden LocatorService Klassen in den App.xaml aufzunehmen und erwartet WPF beiden Klassen wie WinRT oder WinPhone Macht zu laufen. WPF scheint sich nur auf eine Klasse zu beziehen, wenn die Daten benötigt werden. Genau wie im Beispiel des Blogs hatte ich in der Main.xaml Daten an die LocatorService Klasse gebunden. Da die WPF-Anwendung nur den Code dieser Klasse ausführt, wird der Fehler ausgegeben.

Die Lösung bestand darin, die LocatorService Dateien in eine Datei auf der Projektseite WPF zu kombinieren. Warum auf der WPF Seite fragen Sie? A Portable Class Library sollte nur universellen Code enthalten, gemeinsam plattformübergreifend.

0

Wie halte ich, wird IoC-Container versucht MainWindow zu lösen und um es Behälter IDataService löst zu machen. Aber IDataService hat Abhängigkeit IStorageService, die nicht in IoC-Container registriert ist.

Aus meiner Sicht ist IStorageService nicht registriert, weil DeviceLocatorService Konstruktor nie aufgerufen wird.

Ich rechne damit, Sie haben ein Problem mit app.xaml

<Application 
    x:Class="SampleApp.App" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:ignore="http://www.ignore.com" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    mc:Ignorable="d ignore"  
    xmlns:services="using:SampleApp.Services" 
    xmlns:local="using:SampleApp"> 

    <Application.Resources> 
     <ResourceDictionary> 

      <services:LocatorService x:Key="Locator" d:IsDataSource="True" /> 
      <services:DeviceLocatorService x:Key="Locator.W8" d:IsDataSource="True" /> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 
+0

Wie Sie jetzt sehen, habe ich "DeviceLocatorService" in der Datei "App.xaml" hinzugefügt. –

+0

@Steven_BDawg Können Sie versuchen, einen Namespace in App.xaml zu verwenden? – Valentin

+0

Ich verwende einen Namensraum. –

Verwandte Themen