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

时间:2012-10-04 06:55:06

标签: wpf mvvm

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

为了实现这一点,我在模型中添加了一个布尔属性来指示Item是否已更改或注释。但问题是,无论何时更改任何其他属性,我都看不到设置此布尔属性的任何方法。

任何人都可以帮我怎么做吗?

修改 我有一个SelectedItem属性,我假设每当在GridView中选择一个Item时,用户将更新或插入该行。所以在SelectedItem属性上我将SelectedItem的布尔属性设置为True。在循环保存记录时,我保存所有那些在其布尔属性中具有True的记录。我知道它不是完美的方式,但现在我没有任何其他方法可以做到这一点。你的想法?

3 个答案:

答案 0 :(得分:2)

如果您愿意依赖构建时工具,可以使用ILWeaving执行此操作。

因此,如果您将FodyPropertyChanged插件结合使用,则可以直接支持IsDirty功能。

然后Martins的例子可以简化为这个

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");
            }
        }
    }
}

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

具有IsDirty-Flag的类的示例:

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,您还可以添加一个事件处理程序来跟踪新添加或删除的行