在WPF MVVM绑定中检查已更改的属性

时间:2018-04-25 09:00:39

标签: mvvm data-binding inotifypropertychanged

我正在绑定像这样的对象的属性:

视图模型

public class VieModel
{
    public Model MyModel 
    { 
        get
        {
            return myModel;
        } 
        set
        {
            myModel = value;
        }
    }
    private Model myModel
}

模型

public class Model
{
    public string Name { get; set;}
    public string Info { get; set;}
    public string MoreInfo { get; set;}
}

查看

<TextBox Text="{Binding MyModel.Name, Mode=TwoWay, Mode=TwoWay, UpdateSourceTrigger=LostFocus }" />
<TextBox Text="{Binding MyModel.Info, Mode=TwoWay, UpdateSourceTrigger=LostFocus }" />
<TextBox Text="{Binding MyModel.MoreInfo, Mode=TwoWay, UpdateSourceTrigger=LostFocus }" />

一切正常,但当MyModel发生变化时,我想检查是否有任何属性发生变化,以便我可以要求用户先保存。

所以我的第一个想法是添加一个布尔值,在任何更改时都会变为true,因此我可以在MyModel的setter中检查它。但是,当我更改房产时,即使它在后台运行,我目前也没有收到关于MyModel的通知。

总而言之,我得到它,因为MyModel并没有真正改变..但我如何检测任何属性的任何变化?

提前致谢! :)

答案:

要检查当前MyModel是否与旧版本相同,您需要存储该对象的副本以便能够比较它们,如Bijington所述here

为此您可以手动执行或使用二进制序列化程序,以便克隆您的mobject。

手动:

public class Model
{
    public string Name { get; set;}
    public string Info { get; set;}
    public string MoreInfo { get; set;}

    public static Model Clone(Model obj)
    {
        Model newModel = new Model();

        newModel.Name = obj.Name; 
        newModel.Info = obj.Info; 
        newModel.MoreInfo = obj.MoreInfo; 

        return newModel;
    }
}

BinaryFormatter.Serialize

您需要Model中使用的每个对象才能拥有[Serializable]属性。

[Serializable]
public class Model
{
    public string Name { get; set;}
    public string Info { get; set;}
    public string MoreInfo { get; set;}
    public SecondModel SecondOne { get; set;}

    public static Model Clone(Model obj)
    {
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;
            return (T)formatter.Deserialize(ms);
        }
    }
}

[Serializable]
public class SecondModel 
{
    public string SecondName { get; set;}
    public string SecondInfo { get; set;}
    public string SecondMoreInfo { get; set;}
}

1 个答案:

答案 0 :(得分:0)

我从最初的评论中略微改变了我的做法。我没有实现IComparer选项,而是覆盖Equals方法。

public class Model
{
    public string Name { get; set; }
    public string Info { get; set; }
    public string MoreInfo { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is Model model)
        {
            return string.Equals(this.Name, model.Name, StringComparison.Ordinal);
            // && Add your other property comparisons here...;
        }

        return false;
    }

    public override int GetHashCode()
    {
        // You really should provide your implementation here:
        return base.GetHashCode();
    }
}

然后,如上所述设置Model类后,可以在ViewModel类中进行检查:

public class VieModel
{
    private Model myModel;

    public Model MyModel
    {
        get
        {
            return myModel;
        }
        set
        {
            if (myModel?.Equals(value) != true)
            {
                // The model has changed so you can perform what you want here...


                myModel = value;
            }
        }
    }
}