MVVM:如何使清理模型的视图模型集字段保持对数据库的视图更改

时间:2013-01-04 17:47:10

标签: mvvm prism

在具有清洁模型的MVVM应用程序中(未实现INotifyPropertyChabged等接口),View Model包含绑定到View的属性,这些属性从视图模型中包含的模型对象获取其值,并应在设置其属性的值时视图更改绑定到这些属性的控件之一。 问题在于观点发生变化;更改由绑定视图模型属性捕获,但属性无法设置模型对象字段,模型不会更改。我需要模型字段接受视图模型属性的设置,然后我可以将更新的模型保存到数据库中,同时考虑到它是一个干净的模型。

这里是视图模型代码的一部分

public class SubsystemDetailsViewModel: INotifyPropertyChanged, ISubsystemDetailsViewModel
    {
        #region Fields
        //Properties to which View is bound
        private int? _serial;
        public int? Serial
        {
            get { return Subsystem.Serial; }
            set
            {
                //Subsystem.Serial=value;
                _serial = value;
                OnPropertyChanged("Serial");
            }
        }

        private string _type;
        public string Type
        {
            get { return Subsystem.Type; }
            set
            {
                //Subsystem.Type = value;
                _type = value;
                OnPropertyChanged("Type");
            }
        }


       //remaining properties ....


        #endregion

        //Service
        private readonly ISubsystemService _subsystemService;



        //Reference to the View
        public ISubsystemDetailsView View { get; set; }

        //Event Aggregator Event
        private readonly IEventAggregator eventAggregator;

        //Commands
        public ICommand ShowTPGCommand { get; set; }
        public DelegateCommand UpdateCommand { get; set; }

       //
        private bool _isDirty;

        //Constructor ************************************************************************************************
        public SubsystemDetailsViewModel(ISubsystemDetailsView View, ISubsystemService subsystemService, IEventAggregator eventAggregator)
        {
            _subsystemService = subsystemService;

            this.View = View;
            View.VM = this;

            //EA-3
            if (eventAggregator == null) throw new ArgumentNullException("eventAggregator");
            this.eventAggregator = eventAggregator;
            //Commands
            this.ShowTPGCommand = new DelegateCommand<PreCommissioning.Model.Subsystem>(this.ShowTestPacks);
            this.UpdateCommand = new DelegateCommand(this.UpdateSubsystem, CanUpdateSubsystem);


        }


        //****************************************************************************************************************
        //ICommand-3 Event Handler 
        //this handler publish the Payload "SelectedSubsystem" for whoever subscribe to this event
        private void ShowTestPacks(PreCommissioning.Model.Subsystem subsystem)
        {
            eventAggregator.GetEvent<ShowTestPacksEvent>().Publish(SelSubsystem);
        }
        //===============================================================================================
        private void UpdateSubsystem()
        {

            _subsystemService.SaveChanges(Subsystem);
        }

        private bool CanUpdateSubsystem()
        {
            return _isDirty;
        }
        //*******************************************************************************************
        public void SetSelectedSubsystem(PreCommissioning.Model.Subsystem subsystem)
        {
            this.SelSubsystem = subsystem;

        }

        //************************************************************************************************************
        /// <summary>
        /// Active subsystem >> the ItemSource for the View
        /// </summary>
        private PreCommissioning.Model.Subsystem _subsystem;
        public PreCommissioning.Model.Subsystem Subsystem
        {
            get
            { 
                //return this._subsystem;
                GetSubsystem(SelSubsystem.SubsystemNo);
                return this._subsystem;

            }

            set
            {
                if (_subsystem != value)
                {
                    _subsystem = value;
                    OnPropertyChanged("Subsystem");
                }

            }

        }



        //Call the Service to get the Data form the Database
        private void GetSubsystem(string SSNo)
        {
            this._subsystem = _subsystemService.GetSubsystem(SSNo);


        }





        #region Implementation of INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            _isDirty = true;
            UpdateCommand.RaiseCanExecuteChanged();

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

    }
}

子系统是使用GetSubsystem()方法填充的模型对象。像Serial这样的视图模型属性从模型中获取其值,如图所示。我试图设置模型属性,如属性的set部分中注释掉的行所示,但子系统对象没有发生变化,始终保持其原始值

2 个答案:

答案 0 :(得分:1)

如果GetSubsystem每次都返回一个新的子系统,那就是你的问题。在您绑定到视图的属性的“set”中,您将调用公共属性“Subsystem”,而不是您创建的私有字段。因此,每次从视图中设置属性时,都会调用调用GetSubsystem(SelSubsystem.SubsystemNo);的Subsystem.get。

我认为,在“ViewModel属性”中,您希望将其更改为:

//Properties to which View is bound
public int? Serial
{
    get { return _subsystem.Serial; }
    set
    {
        _subsystem.Serial=value; // NOTE THE USE OF THE PRIVATE FIELD RATHER THAN THE PROPERTY
        OnPropertyChanged("Serial");
    }
}

public string Type
{
    get { return _subsystem.Type; }
    set
    {
        _subsystem.Type = value; // NOTE THE USE OF THE PRIVATE FIELD RATHER THAN THE PROPERTY
        OnPropertyChanged("Type");
}

答案 1 :(得分:0)

您需要在视图模型中为模型提供引用,并且视图模型会将值传递给模型。您的视图模型将实现INotifyPropertyChanged,并将成为视图的datacontext。在视图模型中,编写绑定属性,如下所示:

private string yourProperty;
public string YourProperty
{
get { return yourProperty; }
set
{
if (value == yourProperty)
    return;
yourProperty= value;
YOUR_MODEL_REFERENCE.YourProperty= yourProperty;
this.RaisePropertyChanged(() => this.YourProperty);
}
}