gpt4 book ai didi

c# mvvm IEqualityComparer with IChangeTracking

转载 作者:行者123 更新时间:2023-12-03 10:58:48 25 4
gpt4 key购买 nike

我正在努力实现以下目标:
我有一个表单,用户必须输入姓名、姓氏、地址……以及保存更改按钮。
我想让用户点击保存更改 仅当他确实进行了任何更改时才按下按钮。我发现通过简单地使用 IChangeTracking 它只跟踪用户是否完成了 任意 更改工具,但他是否应将更改恢复回来,这不再反射(reflect)。因此,每当我看到已进行更改时,我都会触发 IEqualityComparer;但是没有运气,因为它给了我以下错误:

An unhandled exception of type 'System.StackOverflowException' occurred in Unknown Module.



这是我的简单类Person:
public class Person : ViewModelBase
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
}
}

private string _Surname;
public string Surname
{
get { return _Surname; }
set
{
_Surname = value;
OnPropertyChanged("Surname");
}
}
}

这是我的 ViewModelBase 结构:

public abstract class ViewModelBase : INotifyPropertyChanged, IChangeTracking, IEqualityComparer<Person>
{
public event Action ValueChanged;
protected ViewModelBase()
{
this.PropertyChanged = new PropertyChangedEventHandler(OnNotifiedOfPropertyChanged);
ValueChanged += ViewModelBase_ValueChanged;
}

void ViewModelBase_ValueChanged() {/*do nothing*/ }

public bool Equals(Person x, Person y)
{
if (x == null || y == null)
return false;

return (x.Name == y.Name && x.Surname == y.Surname);
}

public int GetHashCode(Person obj)
{
return obj.GetHashCode();
}

private void OnNotifiedOfPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e != null && !String.Equals(e.PropertyName, "IsChanged", StringComparison.Ordinal))
{
this.IsChanged = true;
}
}

public void AcceptChanges()
{
this.IsChanged = false;
}

public bool IsChanged
{
get
{
lock (_notifyingObjectIsChangedSyncRoot)
{
return _notifyingObjectIsChanged;
}
}

set
{
lock (_notifyingObjectIsChangedSyncRoot)
{
_notifyingObjectIsChanged = value;

this.OnPropertyChanged("IsChanged");

this.ValueChanged.Invoke();
}
}
}

private bool _notifyingObjectIsChanged;
private readonly object _notifyingObjectIsChangedSyncRoot = new Object();

public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));//<<<<<Mentioned Error occures here
}
}
}


最后,这是我设置 ViewModel 的方式:
public class MainViewModel
{
public Person osoba { get; set; }
public Person OldOsoba { get; set; }
public MainViewModel()
{
osoba = new Person();
osoba.Name = "John";
osoba.Surname = "Doe";
osoba.AcceptChanges();

OldOsoba = new Person();
OldOsoba.Name = "John";
OldOsoba.Surname = "Doe";
OldOsoba.AcceptChanges();

osoba.ValueChanged += osoba_ValueChanged;
}

void osoba_ValueChanged()
{
osoba.IsChanged = osoba.Equals(OldOsoba);
}
}

我愿意接受任何建议,因为我不太确定这是否是正确的方法。

最佳答案

这是一个替代方案:

在您的模型中创建 是脏的属性,如果 Name 或 Surname 属性发生更改,该属性将设置为 true:

public class Person : ViewModelBase
{
public string OldName { get; set; }
public string OldSurname { get; set; }

private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
OnPropertyChanged("IsDirty");
}
}

private string _Surname;
public string Surname
{
get { return _Surname; }
set
{
_Surname = value;
OnPropertyChanged("Surname");
OnPropertyChanged("IsDirty");
}
}

public bool IsDirty
{
get
{
return this.Name != this.OldName && this.Surname != this.OldSurname;
}
}
}

注意:为 IsDirty 属性甚至基类使用接口(interface)可能是个好主意。

然后,您可以为您的 ViewModel 实现一个命令,该命令将测试列表中的任何人是否已更改:
public class SaveChangesCommand : ICommand
{
private MainViewModel _viewModel;

public SaveChangesCommand(MainViewModel viewModel)
{
_viewModel = viewModel;
}

public bool CanExecute(object parameter)
{
//People should be an ObservableCollection<Person> in your view model.
return _viewModel.People.Any(x => x.IsDirty);
}

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}

public void Execute(object parameter)
{
_viewModel.SaveChanges();
}
}

在您的 View 模型中创建此命令的实例:
public SaveChangesCommand SaveChangesCommand { get; set; }

不要忘记实例化它(在您的构造函数中将是一个好地方)

并在您的 View 中绑定(bind)一个按钮:
<Button Command="{Binding SaveChangesCommand}" Content="Save Changes"/>

现在,有了这一切,当您的任何模型变脏时,保存更改按钮将被启用。单击后,它将调用 保存更改 View 模型中的方法。在这里,您将需要实现保存更改实现并将所有模型重置为默认状态(IsDirty = false)

我建议通过 MVVM 教程 here .

关于c# mvvm IEqualityComparer with IChangeTracking,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27921844/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com