我试图在视图模型中维护相同类型列表的两个副本。一个列表是视图模型绑定到的基本模型的属性,另一个列表是视图模型的属性。我的目的是让其中一个副本成为最初加载的列表,以便在任何时候我都可以执行“重置”,将模型的列表更新回原始状态。问题是,每次我更新模型列表中的属性时,它也会更新我试图保留为原始版本的副本中的该属性。它的行为就像我正在创建一个卷影副本,但我用“新”对其进行初始化,所以我不确定为什么我不保留 m_originalSubmissionQuestions 的原始状态。谢谢!
型号:
public class SubmissionModel : ModelBase
{
public int SubmissionId { get; set; }
private bool m_noBuildingPlacedInService;
public bool NoBuildingPlacedInService
{
get { return m_noBuildingPlacedInService; }
set
{
if (m_noBuildingPlacedInService == value)
return;
m_noBuildingPlacedInService = value;
RaisePropertyChanged();
}
}
private bool m_beginPeriodInFollowingYear;
public bool BeginPeriodInFollowingYear
{
get { return m_beginPeriodInFollowingYear; }
set
{
if (m_beginPeriodInFollowingYear == value)
return;
m_beginPeriodInFollowingYear = value;
RaisePropertyChanged();
}
}
public List<SubmissionSectionModel> Sections { get; } = new List<SubmissionSectionModel>();
}
型号:
public class SubmissionSectionModel : ModelBase
{
public bool ShowSectionHeader { get; set; }
public string SectionHeader { get; set; }
public List<SubmissionQuestionModel> Questions { get; } = new List<SubmissionQuestionModel>();
}
型号:
public class SubmissionQuestionModel : ModelBase
{
public int AnswerId { get; set; }
public int SubmissionFk { get; set; }
public short QuestionFk { get; set; }
public List<SubmissionAnswerModel> Answers { get; } = new List<SubmissionAnswerModel>();
private bool m_revisionRequired;
public bool RevisionRequired
{
get { return m_revisionRequired; }
set
{
if (m_revisionRequired == value)
return;
m_revisionRequired = value;
RaisePropertyChanged();
}
}
}
查看型号:
public class SubmissionDetailsViewModel : ViewModelBase
{
private readonly IEventAggregator m_eventAggregator;
private readonly IAOCData m_aocData;
private readonly IUserData m_userData;
private ShowControlEvent m_showControlEvent;
private Guid m_submissionGuid;
private readonly int m_userId;
private bool? m_originalIsNoBuildingsInService = null;
private bool? m_originalIsOneBuildingInService = null;
public SubmissionDetailsViewModel (IEventAggregator eventAggregator, IAOCData aocData, IUserData userData)
{
m_eventAggregator = eventAggregator;
m_aocData = aocData;
m_userData = userData;
Setup_EventAggregator_EventHandlers();
CurrentViewState = Visibility.Collapsed;
}
private void Setup_EventAggregator_EventHandlers()
{
//event raisers
m_showControlEvent = new ShowControlEvent();
//event handlers
m_eventAggregator.EventHandler<ShowControlEvent>(e =>
{
if (e.ShowControlType == Enumerations.ShowControlTypes.AOCDetail)
{
if (!Guid.TryParse(e.Key, out Guid _id))
{
m_showControlEvent.ShowControlType = Enumerations.ShowControlTypes.AOCSearch;
m_eventAggregator.RaiseEvent(m_showControlEvent);
MessageBox.Show("Uknown submission id");
return;
}
//scroll to top and display
CurrentViewState = Visibility.Visible;
//data is already loaded - no reason to do it again
if (_id == m_submissionGuid)
{
return;
}
//clear all prior data
SubmissionModel = null;
DetailLoadingVisibilty = Visibility.Visible;
//set the ID
m_submissionGuid = _id;
//load the data
LoadDataAsync();
}
else if (e.ShowControlType == Enumerations.ShowControlTypes.AOCSearch)
{
CurrentViewState = Visibility.Collapsed;
}
});
}
private SubmissionModel m_submissionModel;
public SubmissionModel SubmissionModel
{
get => m_submissionModel;
set
{
if (m_submissionModel == value)
{
return;
}
m_submissionModel = value;
base.RaisePropertyChanged();
}
}
public void HandleInServiceChange()
{
AnnualOwnerCertificationSubmissionSectionModel _questionSection =
SubmissionModel.Sections.FirstOrDefault();
foreach (var _question in _questionSection.Questions)
{
_question.RevisionRequired = true;
}
}
private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SubmissionModel.NoBuildingPlacedInService) || e.PropertyName == nameof(SubmissionModel.BeginPeriodInFollowingYear))
{
HandleInServiceChange();
}
}
private ObservableCollection<AnnualOwnerCertificationSubmissionQuestionModel> m_originalSubmissionQuestions;
public ObservableCollection<AnnualOwnerCertificationSubmissionQuestionModel> OriginalSubmissionQuestions
{
get { return m_originalSubmissionQuestions; }
set
{
if (m_originalSubmissionQuestions == value)
return;
m_originalSubmissionQuestions = value;
base.RaisePropertyChanged();
}
}
private async void LoadDataAsync()
{
//clear everything
SubmissionModel = null;
//start with getting the submission
SubmissionModel _submission;
_submission = await m_aocData.GetSubmission(m_submissionGuid);
SubmissionModel = _submission;
SubmissionModel.PropertyChanged += Model_PropertyChanged;
SubmissionSectionModel _questionSection = SubmissionModel.Sections.FirstOrDefault();
m_originalSubmissionQuestions = new ObservableCollection<SubmissionQuestionModel>(_questionSection.Questions);
DetailLoadingVisibilty = Visibility.Collapsed;
}
}
如果我正确理解你的问题,我建议你添加深度克隆方法。
例如,像这样:
public class SubmissionAnswerModel
{
// Some Code
public SubmissionAnswerModel DeepClone()
=> new SubmissionAnswerModel()
{
// Init properties and fields
};
}
public class SubmissionQuestionModel : ModelBase
{
public SubmissionQuestionModel DeepClone()
=> new SubmissionQuestionModel()
{
AnswerId = AnswerId,
SubmissionFk = SubmissionFk,
QuestionFk = QuestionFk,
Answers = new List<SubmissionAnswerModel>(Answers.Select(ans => ans.DeepClone()),
RevisionRequired = RevisionRequired
};
// Other Code
}
public class SubmissionSectionModel : ModelBase
{
public SubmissionSectionModel DeepClone()
=> new SubmissionSectionModel()
{
ShowSectionHeader = ,
SectionHeader = ,
Questions = new List<SubmissionQuestionModel> (Questions.Select(qst => qst.DeepClone))
}
// Other Code
}
private async void LoadDataAsync()
{
//clear everything
SubmissionModel = null;
//start with getting the submission
SubmissionModel _submission;
_submission = await m_aocData.GetSubmission(m_submissionGuid);
SubmissionModel = _submission;
SubmissionModel.PropertyChanged += Model_PropertyChanged;
SubmissionSectionModel _questionSection = SubmissionModel.Sections.FirstOrDefault(); // Original
SubmissionSectionModel _questionSectionClone = _questionSectionClone.DeepClone(); // Clone
m_originalSubmissionQuestions = new ObservableCollection<SubmissionQuestionModel>(_questionSectionClone.Questions);
DetailLoadingVisibilty = Visibility.Collapsed;
}
还有很多其他选择。
如果可以进行较大的更改,那么我更愿意从 SubmissionModel 类中删除属性并使用方法返回所需的值。特别是,该列表应立即作为深层副本返回,而不是原始列表。
另外,模型类中 INotifyPropertyChanged 的实现对我来说看起来非常有问题。我更愿意在 SubmissionModel 类中创建自定义事件,并使其余类成为不可变的 DTO。