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
}
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