-1

I have a Window with a DataGrid with Companies in it. A user clicks 'Edit', a new Window opens and the SelectedCompany is passed to the ModifyWindow. Now this all works as expected, and if the user clicks Save on the ModifyWindow the SelectedCompany is updated on sql and the changed are reflected in the DataGrid on the main Companies Window.

However, if the user makes changes to the Company in the ModifyWindow and does not click save but instead closes the Window using the cross (to me clearly saying that they want to throw away this edit) then the Company is still updated on the DataGrid. Here is some code:

From the CompaniesViewModel:

private void ShowEditCompanyWindow()
{
    var modifyCompanyViewModel = new ModifyCompanyViewModel(SelectedCompany);
    modifyCompanyViewModel.ReturnModifiedCompany += LoadModifiedCompany;
    Messenger.Default.Send(modifyCompanyViewModel);
}

private void LoadModifiedCompany(Company modifiedCompany)
{
    var existingCompany = DataGridCompanies.FirstOrDefault(c => c.Id == modifiedCompany.Id);
    var i = DataGridCompanies.IndexOf(existingCompany);
    DataGridCompanies[i] = modifiedCompany;

    var existingSearchCompany = AllSearchCompanies.FirstOrDefault(s => s.Id == modifiedCompany.Id);
    var x = AllSearchCompanies.IndexOf(existingSearchCompany);
    if (existingSearchCompany != null)
    {
        existingSearchCompany.Name = modifiedCompany.Name;
        existingSearchCompany.Town = modifiedCompany.Town;
        AllSearchCompanies[x] = existingSearchCompany;
    }

    SelectedCompany = modifiedCompany;

    SearchCompanyView = CollectionViewSource.GetDefaultView(AllSearchCompanies) as CollectionView;

    Application.Current.MainWindow.Activate();
}

From the ModifyCompanyViewModel:

private async void ProcessCompany(Window window)
{
    var waitView = new WaitView
    {
        Owner = Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive)
    };
    waitView.Show();

    if (await EditCompany())
    {
        ReturnModifiedCompany(SelectedCompany);
        CloseWindow(window);
    }

    waitView.Close();
}

The DataGrid on CompaniesView:

<DataGrid Grid.Row="1" x:Name="CompaniesDataGrid" Margin="5" 
            ItemsSource="{Binding DataGridCompanies}"
            SelectedItem="{Binding SelectedCompany}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Width="*" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Town" Width="*" Binding="{Binding Town}"/>
        <DataGridTextColumn Header="Telephone" Width="*" Binding="{Binding Telephone}"/>
    </DataGrid.Columns>
</DataGrid>

I'm new to MVVM and I'm thinking now that I don't have to do the updating of the Company in the DataGridCompanies as MVVM will handle this for me. My bigger issue though is how the SelectedCompany still changes in the DataGrid even though they have closed the modify window and do not want to commit. I have tried binding the Closing event on the modify window and storing an unmodified Company and return that, however the Company in the DataGrid still changed regardless.

CBreeze
  • 2,925
  • 4
  • 38
  • 93
  • Do you have a `cancel` button on the `ModifyWindow`? Closing it should just do the same thing. – Haukinger Aug 15 '17 at 10:56
  • @Haukinger I don't have a cancel button, I just use the cross on the Window as a form of Cancel (or would like to) – CBreeze Aug 15 '17 at 12:27

1 Answers1

0

You could for example implement the IEditableObject interface in your Company class and call the CancelEdit() method when the window is closed.

The BeginEdit() method should store the "old" property values, e.g.:

string _oldName;

public void BeginEdit() => _oldName = _name;

public void CancelEdit() => Name = _oldName;

public void EndEdit() => _oldName = null;
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Would I really have to store every value that can be edited (over 20 values) or can I just store the `Company` itself? Also, as I use Entity Framework wouldn't this mean that everytime I generated from the Database I would have to go through and Implement that interface on all of my models again? – CBreeze Aug 15 '17 at 14:54
  • You will have to store the old value of each individual property value but you may want to check out the MemberwiseClone() method that creates a shallow copy for you: https://stackoverflow.com/questions/2289420/what-is-the-method-memberwiseclone-doing. Customer is a reference type. To "modify" an EF generated entity class, you could create a partial class in the same assembly and namespace: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods. – mm8 Aug 15 '17 at 14:57
  • So on the begin edit I could use MemberwiseClone(), save the changes through EF and then null it at the EndEdit? I'm still not sure how this breaks the reference between the CompanyWindow and the ModifyWindow, as I type in the TextBoxes in the ModifyWindow the value in the DataGrid in the CompanyWindow is changing – CBreeze Aug 15 '17 at 15:09
  • You should not persist any changes back to the database in BeginEdit(), just save the current values in memory. When you call CancelEdit, you set the property values back to these old values that you saved in the BeginEdit() method. Then the old values will be displayed in the CompanyWindow just like before. – mm8 Aug 15 '17 at 15:13