Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MVVM模式:命令绑定和ViewModel执行之间的中间视图_C#_Wpf_User Interface_Mvvm_Datagrid - Fatal编程技术网

C# MVVM模式:命令绑定和ViewModel执行之间的中间视图

C# MVVM模式:命令绑定和ViewModel执行之间的中间视图,c#,wpf,user-interface,mvvm,datagrid,C#,Wpf,User Interface,Mvvm,Datagrid,场景 一些数据被加载到一个程序中(例如,在一个班级中,每个学生都是一个具有他/她的评估数据的独立实体,对学生的评估),并在数据网格上显示这些数据的摘要。用户选择一些学生,并对他们的评估进行分析。分析过程需要一些参数,因此在分析之前会弹出一个窗口,让用户指定自己喜欢的参数;然后执行分析过程 实施总结 datagrid定义如下,并绑定到ViewModel: <DataGrid x:Name="CachedSamplesDG" ItemsSource="{Binding cachedDataSu

场景 一些数据被加载到一个程序中(例如,在一个班级中,每个学生都是一个具有他/她的评估数据的独立实体,对学生的评估),并在数据网格上显示这些数据的摘要。用户选择一些学生,并对他们的评估进行分析。分析过程需要一些参数,因此在分析之前会弹出一个窗口,让用户指定自己喜欢的参数;然后执行分析过程

实施总结 datagrid定义如下,并绑定到ViewModel:

<DataGrid x:Name="CachedSamplesDG" ItemsSource="{Binding cachedDataSummary}">                    
   <DataGrid.Columns>
      <DataGridTextColumn Header="name" Binding="{Binding name}"/>
      <DataGridTextColumn Header="score" Binding="{Binding score}"/>
   </DataGrid.Columns>
</DataGrid>
a这是我当前流程的示意图,以及我下一步要做的事情

问题 单击按钮时

  • 在MainWindow上应用一些UI更改
  • 弹出处理选项窗口
  • 从ProcessOptions窗口获取设置参数
  • 将选定的datagrid行和用户指定的参数传递给
    SamplesAnalyzeCommand

  • 实现此要求的最佳方法是什么?

    只需使用dialogservice,如

    然后可以在ViewModel中执行类似操作

     var result = this.uiDialogService.ShowDialog("Prozess Options Window", prozessOptionVM);
    
     ...
     var parameter1 = prozessOptionVM.Parameter1;
    

    您可以为流程选项定义另一个模型和ViewModel,然后在SamplesAnalyze命令中显示流程选项视图。当用户完成ProcessOptionView时,主ViewModel会收到通知(例如通过事件处理程序)并完成该过程

    大概是这样的:

    internal class SamplesAnalyzeCommand : ICommand {
       ...
       public void Execute(object parameter)
       {
           this._viewModel.ShowProcessOptions(parameter);
       }
    }
    
    internal class CachedDataSummaryViewModel {
        public string Status {
             get {
                 return this.status;
             }
             set {
                 if (!string.Equals(this.status, value)) {
                     this.status = value;
                     // Notify property change to UI
                 }
             }
        }
        ...
        internal void ShowProcessOptions(object paramter) {
            // Model
            var processOptions = new ProcessOptionsModel() {
                otherInfo = parameter
            };
            // View-Model
            var processOptionsViewModel = new ProcessOptionsViewModel();
            processOptionsViewModel.Model = processOptions;
            // View
            var processOptionsView = new ProcessOptionsView(
                processOptionsViewModel
            );
            // Edit2: Update status
            this.Status = "Selecting process options...";
    
            // You can use the event handler or dialog result
            processOptionsViewModel.OK += this.PerformProcess;
            processOptionsView.ShowDialog();
        }
        private void PerformProcess(object sender, EventArgs e) {
            var processOptionsView = sender as ProcessOptionsView;
            var processOptionsModel = processOptionsView.Model;
            var processOptions = processOptionsModel.Model;          
    
            // Edit2: Update status
            this.Status = "Performing process...";
    
            // use processOptions.OtherInfo for initial info
            // use processOptions.* for process options info
            // and perform the process here
    
            // Edit2: Update status
            this.Status = "Process Done.";
        }
        ...
    }
    class ProcessOptionsModel {
        public object OtherInfo {
            get;
            set;
    
        public int Parameter1 {
            get;
            set;
        }
        public IList<ProcessItem> SelectedItems {
            get;
            set;
        }
        ...
    } 
    class ProcessOptionsViewModel {
        public event EventHandler OK;
        private SamplesAnalyzeCommand model;
        private ICommand okCommand;
        public ProcessOptionsViewModel() {
             this.okCommand = new OKCommand(this.OnOK);
        }
        public SamplesAnalyzeCommand Model {
            get {
                return model;
            }
            set {
                this.model = value;
                // Property changed stuff here
            }
        }
        private void OnOK(object parameter) {
            if (this.OK != null) {
                this.OK = value;
            }
        }
    }
    class ProcessOptionsView {
         // Interacts with it's view-model and performs OK command if
         // user pressed OK or something
    }
    
    }

    请注意,在本例中,我删除了OK事件,因为GetProcessOptions应该一直阻止,直到用户关闭主窗口。如果您希望在FromFile案例中采用响应性方法,那么可能需要处理异步的内容,可以定义getProcessOptionAsync


    在这种情况下,事情可能会变得有点复杂,但我想通过这种方式是可以实现的。

    这是一种好的、实用的方法,但仍然不能完全解决我的问题。我想做的第一件事是在父UI上更改UI。我还想将
    选项窗口从
    CachedDataSummaryViewModel
    中排除。我希望,
    CachedDataSummaryViewModel
    只包含用户定义的参数,而不管它们来自何处。这使得it独立于获取此类参数的逻辑发生的任何更改(例如,我可以将其更改为从持久化存储器读取),我更新了答案。我希望我明白你的意思。
    internal class SamplesAnalyzeCommand : ICommand
        {
            public SamplesAnalyzeCommand(CachedDataSummaryViewModel viewModel)
            {
                _viewModel = viewModel;
            }
    
            private CachedDataSummaryViewModel _viewModel;
    
            public event EventHandler CanExecuteChanged
            { 
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
    
            public bool CanExecute(object parameter)
            {
                // canExecute logic
            }
    
            public void Execute(object parameter)
            {
                // process mess ...
                // Here I need the selected rows of datagird, which "parameter" delegates them.
                // I also need some other parameters for analysis which user can set through another view
            }
        }
    
     var result = this.uiDialogService.ShowDialog("Prozess Options Window", prozessOptionVM);
    
     ...
     var parameter1 = prozessOptionVM.Parameter1;
    
    internal class SamplesAnalyzeCommand : ICommand {
       ...
       public void Execute(object parameter)
       {
           this._viewModel.ShowProcessOptions(parameter);
       }
    }
    
    internal class CachedDataSummaryViewModel {
        public string Status {
             get {
                 return this.status;
             }
             set {
                 if (!string.Equals(this.status, value)) {
                     this.status = value;
                     // Notify property change to UI
                 }
             }
        }
        ...
        internal void ShowProcessOptions(object paramter) {
            // Model
            var processOptions = new ProcessOptionsModel() {
                otherInfo = parameter
            };
            // View-Model
            var processOptionsViewModel = new ProcessOptionsViewModel();
            processOptionsViewModel.Model = processOptions;
            // View
            var processOptionsView = new ProcessOptionsView(
                processOptionsViewModel
            );
            // Edit2: Update status
            this.Status = "Selecting process options...";
    
            // You can use the event handler or dialog result
            processOptionsViewModel.OK += this.PerformProcess;
            processOptionsView.ShowDialog();
        }
        private void PerformProcess(object sender, EventArgs e) {
            var processOptionsView = sender as ProcessOptionsView;
            var processOptionsModel = processOptionsView.Model;
            var processOptions = processOptionsModel.Model;          
    
            // Edit2: Update status
            this.Status = "Performing process...";
    
            // use processOptions.OtherInfo for initial info
            // use processOptions.* for process options info
            // and perform the process here
    
            // Edit2: Update status
            this.Status = "Process Done.";
        }
        ...
    }
    class ProcessOptionsModel {
        public object OtherInfo {
            get;
            set;
    
        public int Parameter1 {
            get;
            set;
        }
        public IList<ProcessItem> SelectedItems {
            get;
            set;
        }
        ...
    } 
    class ProcessOptionsViewModel {
        public event EventHandler OK;
        private SamplesAnalyzeCommand model;
        private ICommand okCommand;
        public ProcessOptionsViewModel() {
             this.okCommand = new OKCommand(this.OnOK);
        }
        public SamplesAnalyzeCommand Model {
            get {
                return model;
            }
            set {
                this.model = value;
                // Property changed stuff here
            }
        }
        private void OnOK(object parameter) {
            if (this.OK != null) {
                this.OK = value;
            }
        }
    }
    class ProcessOptionsView {
         // Interacts with it's view-model and performs OK command if
         // user pressed OK or something
    }
    
    interface IOptionsProvider {
        ProcessOptionsModel GetProcessOptions();
    }
    
    class ProcessOptionsView : IOptionsProvider {
        public ProcessOptionsModel GetProcessOptions() {
             if (this.ShowDialog()) {
                  return this.ModelView.Model;
             }
             return null;
        }
    }
    
    class ProcessOptionsFromFile : IOptionsProvider {
        public ProcessOptionsModel GetProcessOptions() {
             // Create an instance of ProcessOptionsModel from File
        }