2017-02-01 1 views
1

Ich bin mit Caliburn.Micro in C# CRUD Anwendung erstellen, und ich habe einige Master-Detailansicht, die so aussieht:C# Master Detailansicht - Zurückkehren gespeicherte Änderungen

Was ich erreichen will ist , wenn ich einige Änderungen (zum Beispiel ändern ich die Kapazität von 47 bis 50), und dann wählen Sie den anderen Ort, sagen wir Platz 4 und wählen Platz 5 wieder meine Kapazität wird 47, nicht 50 wie es jetzt ist .

Ich habe über OneTime-Bindung nachgedacht und manuell die Bindung an das Viewmodel dann ausgelöst, aber ViewModel sollte die Ansicht nicht kennen, so dass das wie eine schlechte Idee scheint. Mein Code unten.

XAML:

<DataGrid x:Name="Places" 
      Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" 
      Width="290" 
      HorizontalAlignment="Left" 
      CanUserReorderColumns="False" CanUserResizeColumns="False" IsReadOnly="True" 
      AutoGenerateColumns="False" IsSynchronizedWithCurrentItem="False" SelectionMode="Single"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Place" Binding="{Binding Name, Mode=OneTime}" MinWidth="150" 
          Width="SizeToCells" /> 
    </DataGrid.Columns> 
</DataGrid> 
<Grid Grid.Column="0" Grid.Row="2" 
     Width="290" Height="210" 
     HorizontalAlignment="Left" VerticalAlignment="Bottom"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="110" /> 
     <ColumnDefinition Width="180" /> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="30" /> 
     <RowDefinition Height="30" /> 
     <RowDefinition Height="60" /> 
     <RowDefinition Height="30" /> 
     <RowDefinition Height="60" /> 
    </Grid.RowDefinitions> 

    <Label Content="ID" 
      Grid.Column="0" Grid.Row="0" VerticalAlignment="Top" /> 
    <Label Content="Place*" 
      Grid.Column="0" Grid.Row="1" VerticalAlignment="Top" /> 
    <Label Content="Address*" 
      Grid.Column="0" Grid.Row="2" VerticalAlignment="Top" /> 
    <Label Content="Capacity*" 
      Grid.Column="0" Grid.Row="3" VerticalAlignment="Top" /> 
    <Label Content="Comments" 
      Grid.Column="0" Grid.Row="4" VerticalAlignment="Top" /> 

    <TextBox x:Name="SelectedPlace_Id" 
      Grid.Column="1" Grid.Row="0" VerticalAlignment="Top" 
      IsEnabled="False" /> 
    <TextBox x:Name="SelectedPlace_Name" 
      Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" /> 
    <TextBox x:Name="SelectedPlace_Address" 
      Grid.Column="1" Grid.Row="2" 
      Height="55" VerticalAlignment="Top" 
      TextWrapping="Wrap" /> 
    <TextBox x:Name="SelectedPlace_Capacity" 
      Grid.Column="1" Grid.Row="3" VerticalAlignment="Top" /> 
    <TextBox x:Name="SelectedPlace_Comments" 
      Grid.Column="1" Grid.Row="4" Height="55" 
      VerticalAlignment="Top" 
      TextWrapping="Wrap" /> 
</Grid> 
<Button x:Name="DeletePlace" Content="Delete" 
     Grid.Column="0" Grid.Row="3" 
     Width="100" Height="30" Margin="0 0 110 0" 
     HorizontalAlignment="Right" VerticalAlignment="Top" /> 
<Button x:Name="SavePlace" Content="Save" 
     Grid.Column="0" Grid.Row="3" 
     Width="100" Height="30" Margin="0 0 5 0" 
     HorizontalAlignment="Right" VerticalAlignment="Top" /> 

Ansichtsmodell:

class PlacesTabViewModel : TabViewModel 
{ 
    #region Fields 

    private BindableCollection<Place> _places; 
    private Place _selectedPlace; 

    #endregion 

    #region Methods 

    public PlacesTabViewModel() 
    { 
     using (var ctx = new DbCtx(App.DatabasePath)) 
     { 
      _places = new BindableCollection<Place>(ctx.Places.OrderBy(p => p.Name)); 
     } 
    } 

    public override string ToString() 
    { 
     return "Places"; 
    } 

    #endregion 

    #region Events 

    public bool CanDeletePlace => _selectedPlace != null; 

    public bool CanSavePlace => (_selectedPlace != null) && _selectedPlace.IsValid(); 

    public void DeletePlace() 
    { 
     using (var ctx = new DbCtx(App.DatabasePath)) 
     { 
      try 
      { 
       ctx.Entry(SelectedPlace).State = EntityState.Deleted; 
       ctx.SaveChanges(); 
      } 
      catch (DbUpdateException) 
      { 
       //TODO: Error 
       return; 
      } 

      Places.Remove(SelectedPlace); 

      NotifyOfPropertyChange(nameof(Places)); 
      NotifyOfPropertyChange(() => CanDeletePlace); 
      NotifyOfPropertyChange(() => CanSavePlace); 
     } 
    } 

    public void SavePlace() 
    { 
     using (var ctx = new DbCtx(App.DatabasePath)) 
     { 
      try 
      { 
       ctx.Places.Attach(_selectedPlace); 
       ctx.Entry(_selectedPlace).State = EntityState.Modified; 
       ctx.SaveChanges(); 
      } 
      catch 
      { 
       //TODO: Error 
      } 

      NotifyOfPropertyChange(nameof(Places)); 
     } 
    } 

    #endregion 

    #region Properties 

    public BindableCollection<Place> Places 
    { 
     get { return _places; } 
     set 
     { 
      if (value != _places) 
      { 
       _places = value; 
       NotifyOfPropertyChange(nameof(Places)); 
      } 
     } 
    } 

    public Place SelectedPlace 
    { 
     get { return _selectedPlace; } 
     set 
     { 
      if (value != _selectedPlace) 
      { 
       _selectedPlace = value; 

       if (_selectedPlace != null) 
       { 
        _selectedPlace.PropertyChanged += (sender, args) => 
        { 
         NotifyOfPropertyChange(() => CanSavePlace); 
        }; 
       } 

       NotifyOfPropertyChange(nameof(SelectedPlace)); 
       NotifyOfPropertyChange(() => CanDeletePlace); 
       NotifyOfPropertyChange(() => CanSavePlace); 
      } 
     } 
    } 

    #endregion 
} 

Ansichtsmodell für die Mainwindow

class MainWindowViewModel : PropertyChangedBase 
{ 
    #region Fields 

    private BindableCollection<TabViewModel> _tabs = new BindableCollection<TabViewModel>(); 

    #endregion 

    public MainWindowViewModel() 
    { 
     _tabs.Add(new PlacesTabViewModel()); 
    } 

    #region Properties 

    public BindableCollection<TabViewModel> Tabs 
    { 
     get { return _tabs; } 
     set 
     { 
      if (value != _tabs) 
      { 
       _tabs = value; 
       NotifyOfPropertyChange(nameof(Tabs)); 
      } 
     } 
    } 

    #endregion 
} 
+2

Es gibt keine Magie, Sie müssen es schreiben. Binden Sie an SelectedItem, und achten Sie auf eine Änderung. Wenn Sie einen Ort auswählen, erhalten Sie Ihre Änderungsbenachrichtigung. Klonen Sie das Objekt. Platzieren Sie es in eine CurrentEdit-Eigenschaft, die an den Editor gebunden ist. Nicht gespeicherte Klone verschwinden, wenn Sie SelectedItem wechseln, ohne Speichern zu drücken. Wenn Sie auf Speichern klicken, nehmen Sie den Klon, suchen Sie nach dem Original in der ItemsSource-Sammlung und wechseln Sie sie. Oder kopieren Sie die Eigenschaftswerte aus dem Klon, entweder oder. – Will

Antwort

0

WPF weiß nicht normal Eigenschaften. Sie müssen es entweder zu einer Abhängigkeitseigenschaft machen oder in Ihrem Fall muss Ihre VM INotifyPropertyChanged implementieren. Wenn sich der Wert ändert, wird er automatisch aktualisiert.

Möglicherweise haben Sie die INotifyPropertyChanged-Eigenschaft für SelectedPlace_Capacity nicht angewendet.

Ich denke, dass dies das Problem ist.

Verwandte Themen