4 Stimmen

Problem mit MVVM-Implementierung: Änderungen am ausgewählten Element werden auf die Liste übertragen, was ich nicht möchte

Ich habe also ein Problem, bei dem Sie mir hoffentlich helfen können.

Ich schreibe eine WPF-Anwendung mit MVVM Light als Framework. In dieser Situation habe ich eine Liste von Elementen, und das SelectedItem ist an eine Detailansicht gebunden, wo der Benutzer das Element bearbeiten kann. In diesem Fall gibt es eine Schaltfläche "Speichern" zum expliziten Speichern von Daten.

Mein Problem ist, dass, wenn der Benutzer die Daten bearbeitet, die Änderungen sofort in der Liste angezeigt werden. Wenn der Benutzer den Vorgang abbricht, wird das ausgewählte Element zurückgesetzt, aber es ist immer noch geändert. Wie verhindere ich, dass sich die Änderungen ausbreiten?

Ich habe versucht, eine Klon-Implementierung zu implementieren, aber sobald ich das getan habe, endet MVVM Light's Messaging-System in eine Schleife zu erhalten, was zu einer StackOverflowException aufgrund der Tatsache, dass ich halten das Objekt klonen. Außerdem ist die Klon-Implementierung hässlich.

Haben Sie eine Idee, wie ich das richtig machen kann?

EDIT:

Basis-XAML für die Listenansicht:

    <DataGrid DataContext="{Binding SubJobTypes}"
              ItemsSource="{Binding}"
              SelectedItem="{Binding ElementName=Root, Path=DataContext.SelectedSubJobType, Mode=TwoWay}">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Name}"/>
        </DataGrid.Columns>
    </DataGrid>

Basis-XAML für die Bearbeitungsansicht:

   <StackPanel>
        <StackPanel>
            <StackPanel Orientation="Horizontal" DataContext="{Binding Path=CurrentSubJobType}">
                <TextBlock Text="Name"/>
                <TextBox Text="{Binding Path=Name, Mode=TwoWay}" Width="150"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button Content="{Binding Path=SubmitCommandText, FallbackValue=Submit}" >
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=SaveSubJobTypeCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button Content="Cancel" >
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=CancelCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button Content="Delete">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=DeleteCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
            </StackPanel>
        </StackPanel>
    </StackPanel>

ViewModels sind Standard, werden nicht gepostet

4voto

AxelEckenberger Punkte 16238

Anstatt den Bindungsmechanismus zu deaktivieren, sollten Sie zwei Ansichtsmodelle haben, eines für die Listenelemente und eines für die Detailansicht. Sobald ein Element ausgewählt wird, sendet das Modell für die Listenansicht eine Nachricht über die Änderung einer Eigenschaft. Das Modell der Detailansicht lädt dann die Daten des Elements oder klont das Modell und initialisiert sich selbst mit den Daten. Jetzt kann das Modell der Detailansicht seine lokale Instanz des Modells ändern.

Nach der Fertigstellung werden die Daten in der Datenbank gespeichert und das Modell der Detailansicht sendet eine Nachricht, dass sich das Element geändert hat. Das Listenansichtsmodell empfängt nun die Nachricht und kann das Modell verwenden, um sein Modell der Elementansicht zu ändern, oder Sie können das Elementmodell aus der Datenbank neu laden und dann das Modell der Elementansicht aktualisieren.

Auf diese Weise müssen Sie sich nicht mit dem manuellen Schreiben der Werte in das Modell herumschlagen, und wenn Sie nur das Modell klonen, sollten Sie keine Probleme mit der Nachrichtenübermittlung haben.

1voto

Wonko the Sane Punkte 10396

Es hat den Anschein, dass Sie sowohl in der Master- als auch in der Detailansicht eine (zweiseitige) Bindung an das gleiche Objekt im ViewModel vornehmen.

Mögliche Alternativen sind:

  • eine Kopie des Objekts erstellen
  • zusätzliche Parameter in Ihrem ViewModel erstellen, wie z. B. "EditName", und sie an die Bearbeitungsansicht anstelle des Namens binden. Sie würden anfänglich auf denselben Wert wie die Eigenschaft Name gesetzt werden. Beim Speichern würden Sie this.Name = this.EditName setzen. Beim Abbrechen würden Sie this.EditName = this.Name setzen.

0voto

Scrappydog Punkte 2834

Ich denke, Sie sollten die "TwoWay"-Datenbindung deaktivieren und nur dann Daten in das Modell zurückschreiben, wenn der Benutzer die Schaltfläche "Submit" drückt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X