There is a Contractor.xaml with DataContext:

<Window.DataContext> <local:ViewModel /> </Window.DataContext> 

There is a ContractorDetail.xaml with a DataContext:

 <Window.DataContext> <local:ContractWindowViewModel /> </Window.DataContext> 

The first window displays general information, the second displays all fields with the possibility of editing, the transition is carried out as follows (The selected Contractor is transmitted):

 public void OpenContractorDetailView(object param) { var contractor = param is ContractorType ? param as ContractorType : null; if(contractor != null) { var contractorDetailsView = new ContractorDetailsWindow(); var vm = contractorDetailsView.DataContext is ContractorDetailsWindowViewModel ? contractorDetailsView.DataContext as ContractorDetailsWindowViewModel : null; vm.Contractor = contractor; contractorDetailsView.Owner = Application.Current.MainWindow; contractorDetailsView.WindowStartupLocation = WindowStartupLocation.CenterOwner; contractorDetailsView.ShowDialog(); } } 

The Details button is created in code behind Contractor.xaml.cs. Here is the code:

 var vm = this.DataContext is PackageWindowViewModel ? this.DataContext as PackageWindowViewModel : null; var messageType = vm.MessageType; foreach(var contractor in messageType.Contractors) { ... Button ownerDetails = new Button() { Content = "Детали...", Width = 100, Height = 23, Margin = new Thickness(0, 5, 5, 0), HorizontalAlignment = HorizontalAlignment.Right, Command = new RelayCommand(arg => vm.OpenContractorDetailView(contractor), can => true) }; ... 

As a result, when I edit the fields in a modal window, they change in the main window.

The binding in ContractorDetail is done as follows (In the example, one field of the Contractor object, the other fields are bound as well):

 <TextBox Grid.Column="1" Grid.Row="6" Text="{Binding Path=Contractor.OKTMO, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" Margin="2" /> 

Save button:

 <Button Grid.Row="9" Grid.Column="1" Content="Сохранить" Width="100" Height="25" HorizontalAlignment="Right" Margin="0, 10, 120, 0" Command="{Binding SaveContractorCommad, Mode=OneWay}" /> 

The SaveContractorCommad command is bound to the method: SaveContractorMethod

 private void SaveContractorMethod() { //OnPropertyChanged("Contractor"); } 

ViewModel with property and field in ContractWindowViewModel:

 private ContractorType _contractor; public ContractorType Contractor { get { return _contractor; } set { _contractor = value; OnPropertyChanged("Contractor"); } } 

Question: How to make it so that when the Contractor object changes its value through the TextBox, these changes are applied only by clicking the Save button, and nothing happens when the window is canceled or closed?

    1 answer 1

    For example, make a separate VM for the required fields, and become attached to it. And by clicking Save transfer data from this new VM to the main one.

    In your case, it will look something like this:

     var temporaryContractor = contractor.Clone(); // (*) var vm = (ContractorDetailsWindowViewModel)contractorDetailsView.DataContext; vm.Contractor = temporaryContractor; var contractorDetailsView = new ContractorDetailsWindow() { Owner = Application.Current.MainWindow, WindowStartupLocation = WindowStartupLocation.CenterOwner }; bool? dialogResult = contractorDetailsView.ShowDialog(); if (dialogResult == true) // нужна явная проверка, т. к. может быть false или null contractor.LoadFrom(temporaryContractor); // (*) 

    You will need to add two more methods, mentioned in the lines marked with (*) . The first method should create a copy of the object, the second should take properties from this copy.

     class ContractorType { // текущий код класса public ContractorType Clone() { return new ContractorType() { OKTMO = OKTMO, // ну и остальные тут же }; } public void LoadFrom(ContractorType another) { OKTMO = another.OKTMO; // и т. д. } } 

    Well, or you can save on the second method, if in case of success simply replace the contractor in the place where it is taken from, with a new one. But for this you need to somehow stretch it to that point.

    • I have two windows. One with general information and the second for editing all fields, which opens in a modal window. Now when I edit in a modal window, the values ​​in the main one change. And you need to make them change when you save. Now I have two different vm - endovitskiiy
    • @endovitskiiy: So your values ​​from the second VM are used in the main window in some way. Or some other error, but you did not give the code to make it clear what the problem is. You have to guess. - VladD
    • Slightly changed the text of the question, can now more clearly. - endovitskiiy
    • @endovitskiiy: Okay, better already, but how exactly do you call OpenContractorDetailView ? Where does the parameter come from? - VladD
    • @endovitskiiy: And by the way, param is ContractorType ? param as ContractorType : null; param is ContractorType ? param as ContractorType : null; you can roll up to just param as ContractorType on the idea. - VladD