从命令返回一个值

本文关键字:一个 命令 返回 | 更新日期: 2023-09-27 18:12:42

我试图在我的WPF应用程序中实现MVVM架构,我希望能够在执行命令后修改模型。请注意,我没有使用任何类型的MVVM框架。

我有一个基本的命令类如下:

namespace MyApplication.Commands {
    public abstract class CommandBase : ICommand {
        protected static BackgroundWorker Worker = new BackgroundWorker();
        protected static string _result;
        public string Result {
            get {
                return _result;
            }
            set {
                _result = value;
            }
        }
        public abstract void DoWork(DoWorkEventArgs args);
        public virtual void Execute(object parameter) {
            Worker = new BackgroundWorker();
            Worker.DoWork += (o, args) => DoWork(args);
            Worker.RunWorkerCompleted += (sender, args) => {
                RaiseCanExecuteChanged(EventArgs.Empty);
            };
            Worker.ProgressChanged += (sender, args) => {
                RaiseCanExecuteChanged(EventArgs.Empty);
            };
            Worker.WorkerReportsProgress = true;
            Worker.RunWorkerAsync(parameter);
        }
        public virtual bool CanExecute(object parameter) {
            return !Worker.IsBusy;
        }
        public event EventHandler CanExecuteChanged;
        protected virtual void RaiseCanExecuteChanged(EventArgs e) {
            CanExecuteChanged(this, e);
        }
    }
}

我已经得到了实现这个的实际命令,如下所示:

namespace MyApplication.Commands {
    internal class DoSomethingCommand : CommandBase {
        public override void DoWork(DoWorkEventArgs args) {
            Worker.ReportProgress(0);
            var success = false;
            try {
                var parameter = args.Argument as int?;
                success = DoSomething(parameter);
            } finally {
                args.Result = success;
            }
        }
        private static bool DoSomething(int parameter) {
            // Do something expensive here...
            System.Func func = (arg) => {
                Thread.Sleep(arg);
                return true;
            };
            // etc etc...
            var success = func.Invoke(parameter);
            return success;
        }
    }
}

我使用这种方式来执行昂贵的操作,同时仍然保持MVVM模型。我必须在进度和完成事件中执行RaiseCanExecuteChanged,否则UI将不会更新相应的按钮状态。

然而,现在我想修改正在访问的当前Model的属性(AKA在ListView控制中选择),该属性暴露为ViewModel的属性。我如何在保持MVVM架构的同时做到这一点?

还有什么更好的方法来传递ViewModel的当前状态到我的命令?目前,我使用的是MultiBindingIMultiValueConverter,只允许传递object[]

从命令返回一个值

为什么不在你的命令的构造函数中传递一个引用给你的viewModel,并在一个局部字段中保存它呢?这样你就可以使用它的公开方法和属性来操作整个viewModel。

关于你的第二个问题:

也有传递ViewModel的当前状态到我的命令的任何更好的方法?

你的命令应该在viewModel中实现,所以你不应该提供viewModel的状态。如果不是这样,为什么不通过在控件的CommandParameter属性中传递DataContext来传递整个viewModel呢?