WPF MVVM - 如何检测如果视图是"脏QUOT; [英] WPF MVVM - How to detect if a View is "Dirty"

查看:102
本文介绍了WPF MVVM - 如何检测如果视图是"脏QUOT;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我有一个要求,如果任何字段已被更改/更新视图来通知我的应用程序的用户。

I currently have a requirement to notify my application user if any fields have been changed/updated on a View.

例如,如果用户更改日期字段在视图,然后尝试关闭视图,应用程序将显示一条消息,询问用户继续并丢失更改或取消,使他们可以单击保存按钮。

For example, if the user changes a date field on the View and then tries to close the View, the application would display a message asking the user to Continue and lose changes or Cancel so that they can click the Save button.

问题是:我如何检测到任何数据字段在视图中更改

Problem is: How do I detect that any of the data fields changed in the View?

希望这是有道理的,比你提前,问候,

Hope this makes sense, than you in advance, regards,

推荐答案

您可以采取的一种方法是利用的IChangeTracking INotifyPropertyChanged的接口。

One approach you can take is to leverage the IChangeTracking and INotifyPropertyChanged interfaces.

如果您创建一个抽象基类,您的视图模型从(ViewModelBase),它实现了IChangeTracking和INotifyPropertyChanged的接口继承,你可以有你的视图模型底座安装到的属性更改通知(实际上信令视图模型已被修改),并且将设置的 IsChanged 属性为true来表明该视图模型是脏。

If you create an abstract base class that your view models inherit from (ViewModelBase) which implements the IChangeTracking and INotifyPropertyChanged interfaces, you can have your view model base attach to notification of property changes (in effect signaling that the view model has been modified) and which will set the IsChanged property to true to indicate that the view model is 'dirty'.

使用这种方法,您是通过依靠属性更改通知。数据绑定跟踪更改任何提交由后会重置更改跟踪

Using this approach, you are relying on property change notification via data binding to track changes and would reset the change tracking after any commits are made.

在你所说,你可以处理的Unloaded 或的关闭您的看法事件来检查的的DataContext ;而如果在DataContext实现IChangeTracking可以使用IsChanged属性,以确定是否有任何不被接受已经作了修改

In the case you described you could handle the Unloaded or Closing event of your view to inspect the DataContext; and if the DataContext implements IChangeTracking you can use the IsChanged property to determine if any unaccepted changes have been made.

简单的例子:

/// <summary>
/// Provides a base class for objects that support property change notification 
/// and querying for changes and resetting of the changed status.
/// </summary>
public abstract class ViewModelBase : IChangeTracking, INotifyPropertyChanged
{
    //========================================================
    //  Constructors
    //========================================================
    #region ViewModelBase()
    /// <summary>
    /// Initializes a new instance of the <see cref="ViewModelBase"/> class.
    /// </summary>
    protected ViewModelBase()
    {
        this.PropertyChanged += new PropertyChangedEventHandler(OnNotifiedOfPropertyChanged);
    }
    #endregion

    //========================================================
    //  Private Methods
    //========================================================
    #region OnNotifiedOfPropertyChanged(object sender, PropertyChangedEventArgs e)
    /// <summary>
    /// Handles the <see cref="INotifyPropertyChanged.PropertyChanged"/> event for this object.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">A <see cref="PropertyChangedEventArgs"/> that contains the event data.</param>
    private void OnNotifiedOfPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e != null && !String.Equals(e.PropertyName, "IsChanged", StringComparison.Ordinal))
        {
            this.IsChanged = true;
        }
    }
    #endregion

    //========================================================
    //  IChangeTracking Implementation
    //========================================================
    #region IsChanged
    /// <summary>
    /// Gets the object's changed status.
    /// </summary>
    /// <value>
    /// <see langword="true"/> if the object’s content has changed since the last call to <see cref="AcceptChanges()"/>; otherwise, <see langword="false"/>. 
    /// The initial value is <see langword="false"/>.
    /// </value>
    public bool IsChanged
    {
        get
        {
            lock (_notifyingObjectIsChangedSyncRoot)
            {
                return _notifyingObjectIsChanged;
            }
        }

        protected set
        {
            lock (_notifyingObjectIsChangedSyncRoot)
            {
                if (!Boolean.Equals(_notifyingObjectIsChanged, value))
                {
                    _notifyingObjectIsChanged = value;

                    this.OnPropertyChanged("IsChanged");
                }
            }
        }
    }
    private bool _notifyingObjectIsChanged;
    private readonly object _notifyingObjectIsChangedSyncRoot = new Object();
    #endregion

    #region AcceptChanges()
    /// <summary>
    /// Resets the object’s state to unchanged by accepting the modifications.
    /// </summary>
    public void AcceptChanges()
    {
        this.IsChanged = false;
    }
    #endregion

    //========================================================
    //  INotifyPropertyChanged Implementation
    //========================================================
    #region PropertyChanged
    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    #region OnPropertyChanged(PropertyChangedEventArgs e)
    /// <summary>
    /// Raises the <see cref="INotifyPropertyChanged.PropertyChanged"/> event.
    /// </summary>
    /// <param name="e">A <see cref="PropertyChangedEventArgs"/> that provides data for the event.</param>
    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }
    #endregion

    #region OnPropertyChanged(string propertyName)
    /// <summary>
    /// Raises the <see cref="INotifyPropertyChanged.PropertyChanged"/> event for the specified <paramref name="propertyName"/>.
    /// </summary>
    /// <param name="propertyName">The <see cref="MemberInfo.Name"/> of the property whose value has changed.</param>
    protected void OnPropertyChanged(string propertyName)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    #region OnPropertyChanged(params string[] propertyNames)
    /// <summary>
    /// Raises the <see cref="INotifyPropertyChanged.PropertyChanged"/> event for the specified <paramref name="propertyNames"/>.
    /// </summary>
    /// <param name="propertyNames">An <see cref="Array"/> of <see cref="String"/> objects that contains the names of the properties whose values have changed.</param>
    /// <exception cref="ArgumentNullException">The <paramref name="propertyNames"/> is a <see langword="null"/> reference (Nothing in Visual Basic).</exception>
    protected void OnPropertyChanged(params string[] propertyNames)
    {
        if (propertyNames == null)
        {
            throw new ArgumentNullException("propertyNames");
        }

        foreach (var propertyName in propertyNames)
        {
            this.OnPropertyChanged(propertyName);
        }
    }
    #endregion
}

这篇关于WPF MVVM - 如何检测如果视图是&QUOT;脏QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆