WPF - 将视图模型列表重置回初始状态

问题描述 投票:0回答:1

我试图在视图模型中维护相同类型列表的两个副本。一个列表是视图模型绑定到的基本模型的属性,另一个列表是视图模型的属性。我的目的是让其中一个副本成为最初加载的列表,以便在任何时候我都可以执行“重置”,将模型的列表更新回原始状态。问题是,每次我更新模型列表中的属性时,它也会更新我试图保留为原始版本的副本中的该属性。它的行为就像我正在创建一个卷影副本,但我用“新”对其进行初始化,所以我不确定为什么我不保留 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;
}


    }

wpf data-binding
1个回答
0
投票

如果我正确理解你的问题,我建议你添加深度克隆方法。

例如,像这样:

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。

© www.soinside.com 2019 - 2024. All rights reserved.