Wpf 如何在MVVM中更改另一个属性时更改属性

Wpf 如何在MVVM中更改另一个属性时更改属性,wpf,mvvm,Wpf,Mvvm,我正在为一个项目使用WPF和MVVM。我有一个带有GridView控件的视图。用户可以在网格视图中插入/更新/删除。当任何动作发生时,更改将反映在ViewModel中。这部分工作正常。但是,当我想在数据库中保存更改时,我需要逐个遍历ItemSource中的每个项。这需要额外的时间来完成。我只想处理那些更改的项目 为了实现这一点,我在模型中添加了一个布尔属性,以指示该项是已更改还是已注释。但问题是,每当任何其他属性发生更改时,我看不到任何方法来设置这个布尔属性 有人能帮我怎么做吗 编辑 我有一个S

我正在为一个项目使用WPF和MVVM。我有一个带有GridView控件的视图。用户可以在网格视图中插入/更新/删除。当任何动作发生时,更改将反映在ViewModel中。这部分工作正常。但是,当我想在数据库中保存更改时,我需要逐个遍历ItemSource中的每个项。这需要额外的时间来完成。我只想处理那些更改的项目

为了实现这一点,我在模型中添加了一个布尔属性,以指示该项是已更改还是已注释。但问题是,每当任何其他属性发生更改时,我看不到任何方法来设置这个布尔属性

有人能帮我怎么做吗

编辑
我有一个SelectedItem属性,我假设每当在GridView中选择一个项目时,用户都会更新或插入该行。所以在SelectedItem属性上,我将SelectedItem的布尔属性设置为True。在循环保存记录的同时,我保存了所有布尔属性为True的记录。我知道这不是最好的办法,但现在我没有其他办法。您的想法?

如果您使用MVVM,您应该更改inotifyProperty的实现。您可以添加一些逻辑来在OnPropertyChanged处理程序中设置布尔属性。

如果使用MVVM,您应该实现INotifyPropertyChanged。您可以添加一些逻辑来在OnPropertyChanged处理程序中设置布尔属性。

您可以订阅模型上的PropertyChanged事件,并将标志设置为True。 但请记住,从数据库加载数据后,必须将标志设置为false,因为模型的初始化也将调用propertychanged事件

具有IsDirty标志的类的示例:

public class Sample : INotifyPropertyChanged
{
    private int id;
    private string name;
    private bool isDirty;

    public event PropertyChangedEventHandler PropertyChanged;

    public int Id
    {
        get { return id; }
        set
        {
            if(id != value)
            {
                id = value;
                RaisePropertyChanged("Id");
            }
        }
    }

    public string Name
    {
        get { return name; }
        set
        {
            if (name != value)
            {
                name = value;
                RaisePropertyChanged("Name");
            }
        }
    }

    public bool IsDirty
    {
        get { return isDirty; }
        set
        {
            if (isDirty != value)
            {
                isDirty = value;
                RaisePropertyChanged("IsDirty");
            }
        }
    }

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        if (propertyName != "IsDirty")
        {
            IsDirty = true;
        }

        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

如果您使用的是ObservableCollection,还可以添加eventhandler来跟踪新添加或删除的行

您可以订阅模型上的PropertyChanged事件并将标志设置为True。 但请记住,从数据库加载数据后,必须将标志设置为false,因为模型的初始化也将调用propertychanged事件

具有IsDirty标志的类的示例:

public class Sample : INotifyPropertyChanged
{
    private int id;
    private string name;
    private bool isDirty;

    public event PropertyChangedEventHandler PropertyChanged;

    public int Id
    {
        get { return id; }
        set
        {
            if(id != value)
            {
                id = value;
                RaisePropertyChanged("Id");
            }
        }
    }

    public string Name
    {
        get { return name; }
        set
        {
            if (name != value)
            {
                name = value;
                RaisePropertyChanged("Name");
            }
        }
    }

    public bool IsDirty
    {
        get { return isDirty; }
        set
        {
            if (isDirty != value)
            {
                isDirty = value;
                RaisePropertyChanged("IsDirty");
            }
        }
    }

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        if (propertyName != "IsDirty")
        {
            IsDirty = true;
        }

        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

如果您使用的是ObservableCollection,那么还可以添加eventhandler来跟踪新添加或删除的行

如果您愿意依赖构建时工具,那么可以通过iLwiving实现这一点

所以,如果您与addin相结合,那么IsDirty功能将得到开箱即用的支持

那么马丁斯的例子可以简化为这样

public class Sample : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsChanged { get; set; }
}
注意如果
IsChanged
而不是
IsDirty
,则使用该选项

然后这将存在于编译的程序集中

public class Sample : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    int id;
    public int Id
    {
        get { return id; }
        set
        {
            if (id != value)
            {
                id = value;
                IsChanged = true;
                OnPropertyChanged("Id");
            }
        }
    }

    bool isChanged;
    public bool IsChanged
    {
        get { return isChanged; }
        set
        {
            if (isChanged != value)
            {
                isChanged = value;
                OnPropertyChanged("IsChanged");
            }
        }
    }

    string name;
    public string Name
    {
        get { return name; }
        set
        {
            if (!string.Equals(name, value, StringComparison.Ordinal))
            {
                name = value;
                IsChanged = true;
                OnPropertyChanged("Name");
            }
        }
    }
}

如果您愿意依赖于构建时工具,那么可以使用ILWIVING来实现这一点

所以,如果您与addin相结合,那么IsDirty功能将得到开箱即用的支持

那么马丁斯的例子可以简化为这样

public class Sample : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsChanged { get; set; }
}
注意如果
IsChanged
而不是
IsDirty
,则使用该选项

然后这将存在于编译的程序集中

public class Sample : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    int id;
    public int Id
    {
        get { return id; }
        set
        {
            if (id != value)
            {
                id = value;
                IsChanged = true;
                OnPropertyChanged("Id");
            }
        }
    }

    bool isChanged;
    public bool IsChanged
    {
        get { return isChanged; }
        set
        {
            if (isChanged != value)
            {
                isChanged = value;
                OnPropertyChanged("IsChanged");
            }
        }
    }

    string name;
    public string Name
    {
        get { return name; }
        set
        {
            if (!string.Equals(name, value, StringComparison.Ordinal))
            {
                name = value;
                IsChanged = true;
                OnPropertyChanged("Name");
            }
        }
    }
}

如何使用数据库?如果你使用某种ORM,比如实体框架,它会自动跟踪变化,所以你不必担心,我不会使用任何实体框架。我正在使用System.Data.SqlClient类。您如何使用数据库?如果你使用某种ORM,比如实体框架,它会自动跟踪变化,所以你不必担心,我不会使用任何实体框架。我正在使用System.Data.SqlClient类。我不确定如何在模型上使用PropertyChanged事件。因为我到处都能看到人们在ViewModel上使用它。是的,我使用的是ObservaleCollection,但我没有找到一种方法,即当属性发生更改时,您可以像在ViewModel上一样在模型上使用INotifyPropertyChanged来实现,实现中没有区别。为了简化此接口的使用,我正在使用NOTIFYPROPERTYWAVER()注入所需的通知代码。ObservableCollection不会通知您某个项的更改,但它会通知您某个项是否已添加到集合或已从集合中移除,因此您可能需要这两个项,INotifyPropertyChanged和INotifyCollectionChanged感谢您的回复,我将实施INotifyCollectionChanged,以及它与INotifyPropertyChanged的区别,然后我将带着我的更新返回给您。你能检查我问题的编辑部分并对其进行评论吗?我实现了以下内容,MyViewModel.CollectionChanged+=MyViewModelCollectionChanged;在我的视图模型的构造函数中。但我注意到,只有在ObservableCollection中添加或删除了一个新项时,它才起作用。不适用于更新的项目。我不确定如何在我的模型上使用PropertyChanged事件。因为我到处都能看到人们在ViewModel上使用它。是的,我使用的是ObservaleCollection,但我没有找到一种方法,即当属性发生更改时,您可以像在ViewModel上一样在模型上使用INotifyPropertyChanged来实现,实现中没有区别。为了简化此接口的使用,我正在使用NOTIFYPROPERTYWAVER()注入所需的通知代码。ObservableCollection不会通知您某个项的更改,但它会通知您某个项是否已添加到集合或已从集合中移除,因此您可能需要这两个项,INotifyPropertyChanged和INotifyCollectionChanged感谢您的回复,我将实施INotifyCollectionChanged,以及它与INotifyPropertyChanged的区别,然后我将带着我的更新返回给您。你能检查我问题的编辑部分并对其进行评论吗?我实现了以下内容,MyViewModel.CollectionChanged+=MyViewModelCollectionChanged;在我的视图模型的构造函数中。但我注意到,只有当