如何在单击取消按钮时回滚 WPF 子窗口中更改的数据

本文关键字:窗口 数据 WPF 单击 取消 按钮 | 更新日期: 2023-09-27 17:57:21

好吧,假设我们有一个绑定到DataContextParent Window,现在假设我们触发了一个Child Window并将其数据上下文设置为父窗口的数据上下文。现在,子窗口中的项已绑定到TwoWay模式下的数据上下文。当用户更改此子窗口中的某些内容时,源视图模型中的数据将更新。但是,如果用户用DialogResult == false关闭窗口怎么办?如何将数据回滚到原始数据?

现在,我正在OneWay模式下绑定数据,并且仅在DialogResult == true .但我想一定有一种更优雅的方式来做到这一点。

如何在单击取消按钮时回滚 WPF 子窗口中更改的数据

IEditableObject

与 WPF 可以使用System.ComponentModel.INotifyPropertyChanged相同的方式,您也可以使用接口System.ComponentModel.IEditableObject 。 此接口具有以下有用的方法:

  • BeginEdit()
  • EndEdit() - 我们并不真正需要
  • CancelEdit()

在显示窗口之前,请对数据上下文调用BeginEdit()。 现在,任何更改都通过通常的INotifyPropertyChanged进行反映,以便父级像往常一样接收更新。

如果用户取消,则调用CancelEdit()此时视图模型应回滚更改。 免费的牛排刀是,您的父窗口通过INotifyPropertyChanged被告知回滚,从而也"还原"父窗口。

否则调用EndEdit()老实说不是必需的,因为更改已经完成。

显然,您需要以某种方式记住先前的值,以便可以还原任何更改。

不可更改跟踪

我刚刚阅读了有关System.ComponentModel.IRevertibleChangeTracking它提供了AcceptChanges()RejectChanges()的方法。 尽管可以说这是用于接受回滚更改的接口,但并不完全清楚在此期间所做的更改是否应在 WPF 方案中广播。 也许有人可以在这里帮助我。

告诉我更多...

将绑定上的UpdateSourceTrigger更改为显式,并仅在单击"确定"按钮时调用 UpdateSource 方法。

更新源触发器

例如,您可以在主视图中将确认的值绑定为单向只读值,将未提交的值绑定到对话框文本框。

ViewModel
    class MyVM : MVVM.ViewModel.ViewModelBase
    {
        private string name1;
        public string Name1
        {
            get { return name1; }
            set {
                name1 = value;
                OnPropertyChanged(() => Name1);
            }
        }
        string name1Conf;
        public string Name1Conf
        {
            get { return name1Conf; }
        }
        private string name2;
        public string Name2
        {
            get { return name2; }
            set
            {
                name2 = value;
                OnPropertyChanged(() => Name2);
            }
        }
        string name2Conf;
        public string Name2Conf
        {
            get { return name2Conf; }
        }
        private bool commitMe;
        public bool CommitMe
        {
            get { return commitMe; }
            set {
                commitMe = value;
                OnPropertyChanged(() => CommitMe);
                if (commitMe)
                {
                    DoCommit();
                } 
            }
        }
        private void DoCommit()
        {
            name1Conf = name1;
            name2Conf = name2;
            OnPropertyChanged(() => Name1Conf);
            OnPropertyChanged(() => Name2Conf);
        }
    }

代码隐藏

private void button_Click(object sender, RoutedEventArgs e)
{
    var win2 = new WPFDialog();
    win2.DataContext = myVM;
    var res = win2.ShowDialog();
    myVM.CommitMe = res == true;
}