Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Hi Leute, ich entwickle gerade 'ne Automanger App um den Tankverlauf von Autos zu "loggen".
Aus irgendeinem Grund bekomme ich aber 'nen InvalidOperationException Fehler und weiß nicht, wie ich diesen beheben kann.
Ich hab 'n MainViewModel, welches die Eigenschaft Auto hat (mit NotifyPropertyChanged Event)
Wenn ich nun das MainViewModel bei der Autoauswahl wechseln will und das MainViewModel neu setzen will, bekomme ich den Hinweis "Cannot change ObservableCollection during a CollectionChanged or PropertyChanged event." bei der Zeile wo das Kommentar ist.
Code:
public class MainViewModel : INotifyPropertyChanged
{
[...]
public void Save()
{
ObservableCollection<Auto> collection = new ObservableCollection<Auto>();
if (IsolatedStorageSettings.ApplicationSettings.Contains("Autos"))
{
collection = (ObservableCollection<Auto>)IsolatedStorageSettings.ApplicationSettings["Autos"];
if (collection.Contains(this.aktuellesAuto))
{
Debug.WriteLine("Auto aktualisiert: " + collection.IndexOf(this.aktuellesAuto));
// Fehler
collection[collection.IndexOf(this.aktuellesAuto)] = this.aktuellesAuto; // <----- hier tritt der Fehler auf.
}
else
{
collection.Add(this.aktuellesAuto);
Debug.WriteLine("1. Neues Auto erstellt: " + collection.IndexOf(this.aktuellesAuto).ToString());
AppSettings.aktuelleAutoId = collection.IndexOf(this.aktuellesAuto);
}
}
else
{
collection.Add(this.aktuellesAuto);
Debug.WriteLine("2. Neues Auto erstellt: " + collection.IndexOf(this.aktuellesAuto).ToString());
AppSettings.aktuelleAutoId = collection.IndexOf(this.aktuellesAuto);
}
IsolatedStorageSettings.ApplicationSettings["Autos"] = collection;
IsolatedStorageSettings.ApplicationSettings.Save();
}
[...]
}
Der Fehler tritt aber auch nur auf, wenn ich das Auto zum zweiten Mal wechsel.
Der Aufruf der Save()-Methode kommt aus der AutoListPage.xaml
Code:
public partial class AutoListPage : PhoneApplicationPage
{
[...]
private void ListBox_Autos_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListBox_Autos.SelectedIndex != AppSettings.aktuelleAutoId)
{
App.ViewModel.Save();
AppSettings.aktuelleAutoId = ListBox_Autos.SelectedIndex;
App.ViewModel = new MainViewModel();
}
//NavigationService.Navigate(new Uri("/../MainPage.xaml", UriKind.Relative));
NavigationService.GoBack();
}
[...]
}
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Hallo Erdnuss
Ich sehe den Fehler zwar nicht, aber evtl. hilft es wenn du den Typ der Collection z.B. in List änderst, oder zeigst du diese Collection auf dem GUI an?
Des weiteren bin ich mir überhaupt nicht sicher, ob der Block welcher den Fehler verursacht Sinn macht. Contains überprüft ja, ob genau das Element in der Liste ist, falls ja müsste man es gar nicht mehr anpassen, da das aktuellesAuto und das Auto in der Liste auf das selbe Object im Speicher referenzieren und somit wird der Inhalt automatisch angepasst.
Ich hoffe du Verstehen worauf ich hinaus will
Gruss
Cr3dos
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Hallo,
Da hast du recht, dass es nicht gleichzeitig aktualisiert wird.
Dieses Contains wird meiner Meinung nach immer false zurückgeben, da das Aktuelle Auto nicht auf das selbe referenziert im Speicher wie die Liste, die aus dem Storage geholt wurde.
Aber ich kann es auch nicht 100% sagen, da ich nicht direkt mit dem IsolatedStorage(oder IsolatedStorageSettings) arbeite. Ich benutze das RapidRepository. Würde dir empfehlen dies mal anzuschauen, falls du noch nicht allzu viel gemacht hast.
Gruss
Cr3dos
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Umwandeln ist ganz einfach:
Zitat:
List<Auto> collection = new List<Auto>();
foreach(Auto auto in (ObservableCollection<Auto>)IsolatedStorageSettings.ApplicationSettings["Autos"]){
collection.Add(auto);
}
Habe den Code nicht ausprobiert, sollte aber funktionieren.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Performance mässig spielt dies keine grosse Rolle, da der User in deiner App vermutlich nicht mehr als 10 Autos eintragen wird.
In meiner App MySchool mache ich diese Umwandlung auch und ich bekam noch nie eine Beschwerde wegen Performance-Problemen.
Natürlich kann man auch eine normale Liste nehmen um auf dem GUI anzuzeigen und muss dann nicht jedes mal das Umwandeln machen.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Ich bin mir nicht 100% sicher, ob ich verstanden habe, was du mit dem Code im ersten Post eigentlich machen willst. Ein paar Anmerkungen habe ich aber trotzdem:
- Bei jedem SelectionChanged Event auf den Isolated Storage zuzugreifen ist auch nicht gerade performace-orientiert. Den Aufwand für die Umwandlung einer Liste kannst du völlig vernachlässigen gegenüber Zugriffen auf Isolated Storage.
- Eigentlich sagt die Exception "Cannot change ObservableCollection during a CollectionChanged or PropertyChanged event." ziemlich genau, was das Problem ist. Es geht zwar aus deinem Codebeispiel nicht hervor, aber ich nehme stark an, dass die ListBox_Autos an die ObservableCollection gebunden ist, die du in den IsolatedStorageSettings speicherst? Du kannst die ObservableCollection nicht ändern in einem Event Handler, der von einem potenziell die ObservableCollection ändernden Ereignis ausgeht, da du andernfalls eine "Endlosschleife" produzieren würdest. Du würdest die Collection ändern als Reaktion auf eine Änderung.
Ich hoffe, das war halbwegs verständlich ;)
Eine einfache Lösung habe ich leider gerade nicht parat. Aber mal so ins blaue gefragt: wieso willst du bei jedem SelectionChanged Event den Zustand gleich persistieren?
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Also ich bin jetzt ein wenig verwirrt.^^
Ist es nun besser ne Liste zu binden oder ne ObservableCollection ?
Desweiteren habe ich jetzt nochmal den Speicherzeitpunkt geändert. Es wird nur noch gespeichert, wenn der Nutzer die App richtig schließt.
Nun werden auch am Anfang alle Autos ins MainViewModel in eine ObservableCollection Autos geladen.
Aus dieser wird dann das aktuellesAuto geholt.
Code:
public void LoadData()
{
if (AppSettings.aktuelleAutoId < 0)
{
this.aktuellesAuto.Automarke = "Kein Auto geladen";
this.aktuellesAuto.Modeltyp = "";
this.aktuellesAuto.Kennzeichen = "-";
}
if (IsolatedStorageSettings.ApplicationSettings.Contains("Autos"))
{
this.Autos = (ObservableCollection<Auto>)IsolatedStorageSettings.ApplicationSettings["Autos"];
this.aktuellesAuto = (Auto)Autos[AppSettings.aktuelleAutoId];
this.aktuellesAuto.Tankvorgaenge = new ObservableCollection<Tankvorgang>();
this.aktuellesAuto.Tankvorgaenge.Add(new Tankvorgang() { Liter = 45, Preis = 60, GesamtKilometer = 550, Tankdatum = DateTime.Now, Verbrauch = 6 });
this.aktuellesAuto.Fahrten = new ObservableCollection<Fahrt>();
this.aktuellesAuto.Fahrten.Add(new Fahrt() { Name = "Fahrt X", Beschreibung = "Nach Berlin", Kilometer = 500 });
this.IsDataLoaded = true;
}
}
So wenn ich jetzt das Auto wechseln will, erfolgt folgendes, der Datenkontext ist dabei "ListBox_Autos.DataContext = App.ViewModel;".
Code:
private void ListBox_Autos_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListBox_Autos.SelectedIndex != AppSettings.aktuelleAutoId)
{
App.ViewModel.Autos[AppSettings.aktuelleAutoId] = App.ViewModel.aktuellesAuto;
AppSettings.aktuelleAutoId = ListBox_Autos.SelectedIndex;
App.ViewModel.aktuellesAuto = App.ViewModel.Autos[AppSettings.aktuelleAutoId];
}
//NavigationService.Navigate(new Uri("/../MainPage.xaml", UriKind.Relative));
NavigationService.GoBack();
}
und wenn ich nun das Auto wechseln will, sagt er mir bei "App.ViewModel.Autos[AppSettings.aktuelleAutoId] = App.ViewModel.aktuellesAuto;", den gleichen Fehler wie am Anfang. Mit dem Wissen von dir leitning ist das nun klar. Nur stellt sich mir die Frage warum? Wenn sich die Selektion der ListBox ändert, dann will ich das aktuellesAuto ja in der ObservableCollection aktualisieren und das ausgewählte neue Auto als aktuellesAuto setzen. Wenn ich das aktuellesAuto während der Laufzeit ändere, wird es doch nicht gleichzeitig in der ObservableCollection geändert, oder?
So und naja sie war nicht gebunden, nein. Die Collection war nur in der SaveMethode lokal vorhanden.
Jetzt ist das ganze ViewModel (MainViewModel) an die ListBox_Autos gebunden, weil irgendwie bei ViewModel.Autos ich immer gesagt bekomme in der Ausgabe, dass der Pfad nicht stimmt. :/
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Zitat:
Zitat von
ErdnussFlipS
Wenn ich das aktuellesAuto während der Laufzeit ändere, wird es doch nicht gleichzeitig in der ObservableCollection geändert, oder?
Ich weiss nicht wie sehr du dich mit der OO-Programmierung / C# bis jetzt befasst hast.
Das Item in der ObservableCollection beinhaltet eine Referenz auf den Speicher. Im Speicher sind die genau Daten abgelegt z.B. die genau Tankvorgang, Fahrten etc. Weist du einer anderen Variable das Auto zu, also in deinem Fall "this.aktuellesAuto = (Auto)Autos[AppSettings.aktuelleAutoId];" sagst du nichts anderes als "Die Variable aktuellesAuto zeigt auf die selbe Position im speicher wie das Auto an der Position AppSettings.aktuelleAutoId" (Anmerkung: den cast ("(Auto)") kann man weglassen)
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Ja doch, das mit dem Speicher hatte ich eig schonmal gelesen. Aber ich nehm das noch nicht so richtig für voll.
Nur was bedeutet das dann im Endeffekt?
EDIT: Das komische an der Ganzen Sache ist nur, dass ich das Auto ja einmal wechseln kann. Also "ListBox_Autos_SelectionChanged" wir ja einmal ausgeführt, nur nach einem weiteren Wechsel oder einem weiteren Versuch des Wechselns, bekomme ich die Exception.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Zitat:
Nur was bedeutet das dann im Endeffekt?
Du kannst die Zeile löschen: "App.ViewModel.Autos[AppSettings.aktuelleAutoId] = App.ViewModel.aktuellesAuto;". Die zeigen beide auf das selbe.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Ah okay.. Dann müsste das ja funktionieren. Und die Collection ist dann ja auch aktuell.
EDIT: Also das mit dem wechseln funktioniert jetzt.
Noch ne andere Frage, egal was ich nun mache die ListBox_Autos_SelectionChanged-Methode ist jetzt nur noch am rummeckern. -.- Also die will sich jetzt immer aufrufen, immer wenn sich die gebundene Collection ändern, also im Moment wenn ich alle Autos lösche. Kann ich diesen Aufruf irgendwie stoppen, also das Event?
Code:
private void ListBox_Autos_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListBox_Autos.SelectedIndex != AppSettings.aktuelleAutoId && ListBox_Autos.SelectedIndex >= 0)
{
AppSettings.aktuelleAutoId = ListBox_Autos.SelectedIndex;
App.ViewModel.aktuellesAuto = App.ViewModel.Autos[AppSettings.aktuelleAutoId];
}
NavigationService.GoBack();
}
Das NavigationService.GoBack(); meckert er an und sagt, dass schon ein NavigationProcess läuft.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Meiner Meinung nach, wenn du sicher gehen willst kannst du ja debuggen
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Hi, ich hab jetzt ein ganz anderes Problem.
Ich hatte den Code n bisschen umgeschrieben, nun schmiert mir die App immer ab, wenn ich "IsolatedStorageSettings.ApplicationSettings.Save();" aufrufe. Der Debugger gibt mir auch nichts aus. Habt ihr ne Idee, wie ich herausfinden kann warum es abschmiert?
Das ist die Methode
Code:
public void Save()
{
Debug.WriteLine("Save(): " + AppSettings.aktuelleAutoId);
if (AppSettings.aktuelleAutoId >= 0)
{
Debug.WriteLine("Fehler nach setzen.");
IsolatedStorageSettings.ApplicationSettings["Autos"] = this.Autos;
try
{
Debug.WriteLine("Fehler vor Save()");
IsolatedStorageSettings.ApplicationSettings.Save();
Debug.WriteLine("Kein Fehler");
}
catch (IsolatedStorageException)
{
Debug.WriteLine("Fehler");
throw;
}
}
}
Debug.WriteLine("Fehler vor Save()"); gibt er noch aus, "Debug.WriteLine("Kein Fehler");" schon nicht mehr.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Zitat:
try
{
Debug.WriteLine("Fehler vor Save()");
IsolatedStorageSettings.ApplicationSettings.Save();
Debug.WriteLine("Kein Fehler");
}
catch (Exception e)
{
Debug.WriteLine(e);
}
ausprobieren
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Hab ich versucht. Er catcht die Exeption nicht.
Hab das So drinne:
Code:
Debug.WriteLine("Save(): " + AppSettings.aktuelleAutoId);
if (AppSettings.aktuelleAutoId >= 0)
{
Debug.WriteLine("Fehler nach setzen.");
IsolatedStorageSettings.ApplicationSettings["Autos"] = this.Autos;
try
{
Debug.WriteLine("Fehler vor Save()");
IsolatedStorageSettings.ApplicationSettings.Save();
Debug.WriteLine("Kein Fehler");
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e);
}
}
Die Ausgabe ist dann:
Zitat:
Save(): 0
Fehler nach setzen.
Fehler vor Save()
Der Thread '<Kein Name>' (0x27790dee) hat mit Code 0 (0x0) geendet.
Der Thread '<Kein Name>' (0x260e08fa) hat mit Code 0 (0x0) geendet.
Der Thread '<Kein Name>' (0x264c0766) hat mit Code 0 (0x0) geendet.
Das Programm "[647564254] UI Task: Verwaltet" wurde mit Code 0 (0x0) beendet.
EDIT: Wenn ich "IsolatedStorageSettings.ApplicationSettings["Autos"] = this.Autos;" rausnehme, stürzt er nicht ab. Muss also an der Collection Autos liegen oder am MainViewModel.
AW: Bekomme InvalidOperationException Fehler und weiß nicht wie ich es lösen kann.
Problem gelöst. War ein Fehler in der Klasse Auto.^^
Funktioniert jetzt. :)