Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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
Wpf 如何在同一ViewModel中使用不同的行为?_Wpf_Oop_Mvvm - Fatal编程技术网

Wpf 如何在同一ViewModel中使用不同的行为?

Wpf 如何在同一ViewModel中使用不同的行为?,wpf,oop,mvvm,Wpf,Oop,Mvvm,我的视图是为长时间运行的任务设计的。它有一个标题和一个进度条。 因此,该模型具有标题文本、进度条计数器和TotalAmountOfWork字段。该模型还具有 public delegate void TaskCompleted(string resultDescription); public event TaskCompletedCopyingCompletedEvent; public event Action UpdateViewState; 当计数器更改时,模型将调用UpdateVie

我的视图是为长时间运行的任务设计的。它有一个标题和一个进度条。 因此,该模型具有标题文本、进度条计数器和TotalAmountOfWork字段。该模型还具有

public delegate void TaskCompleted(string resultDescription);
public event TaskCompletedCopyingCompletedEvent;
public event Action UpdateViewState;
当计数器更改时,模型将调用UpdateViewState。 ViewModel已订阅事件,并在其打开视图时进行更新

嗯。我有两个类用于将文件从硬盘复制到闪存驱动器,还有一个类用于检索诊断信息,这些信息最终也应复制到闪存驱动器

我想在同一个ViewModel中使用它们,但我不知道如何避免代码重复。我不知道如何依靠正确的面向对象设计来实现它

这三个类可以实现如下接口:

interface ILongRunningTask {
    void DoWork();
}
public class FilesCopyingViewModel: Screen {       
    private readonly FilesCopyingModel model;
    private readonly IWindowManager windowManager;

    public int CurrentProgress {
        get { return model.CurrentProgressValue; }
    }

    public int FilesCountToCopy {
        get { return model.FilesCountToCopy; }
    }

    [ImportingConstructor]
    public LongRunningViewModel(IFilesCopier copier) {
        model = copier as FilesCopyingModel;
        model.CopyingCompletedEvent += CopyingCompletedHandler;
        model.UpdateViewState += UpdateViewStateHandler;
        windowManager = new WindowManager();
    }

    private void UpdateViewStateHandler() {
        NotifyOfPropertyChange(() => CurrentProgress);
        NotifyOfPropertyChange(() => FilesCountToCopy);
    }

    private void CopyingCompletedHandler(string resultDescription) {
        //some code
    }

    private void RemoveDriveSafely() {
        //some code
    }

    private void PromptEjection(string result) {
        //some code
    }

    private void PromptSuccessEjection() {
        //some code
    }

    private void PromptEjectFlashError() {
        //some code
    }

    protected override void OnActivate() {
        try {
            var copier = (IFilesCopier) model;
            Task.Factory.StartNew(copier.Copy);
        }
        catch (Exception ex) {
            //error handling
        }
    }
}
然后我可以以ILongRunningTask为参数实现ViewModel

但是看看接口的名称。它看起来太笼统了。这样的抽象似乎有问题

嗯。在我看来,ViewModel应该接受委托才能调用长时间运行的任务。但在这种情况下,ViewModel将如何与更新其属性的模型交互

//更新 现在,模型看起来像:

public class FilesCopyingModel : IFilesCopier {
    protected int filesCountToCopy;
    public int FilesCountToCopy {
        get { return filesCountToCopy; }
        set {
            filesCountToCopy = value;
            InvokeUpdateViewState();
        }
    }

    protected int currentProgressValue;
    public int CurrentProgressValue {
        get { return currentProgressValue; }
        set {
            currentProgressValue = value;
            InvokeUpdateViewState();
        }
    }

    public delegate void CopyingCompleted(string resultDescription);

    public event CopyingCompleted CopyingCompletedEvent;
    public event Action UpdateViewState;

    private readonly IFilesCopier filesCopier;

    protected FilesCopyingModel() {
    }

    public FilesCopyingModel(IFilesCopier filesCopier) {
        if (filesCopier == null)
            throw new ArgumentNullException("filesCopier");
        this.filesCopier = filesCopier;
    }

    protected static string GetCurrentDateTime() {
        return DateTime.Now.ToString("dd.MM.yyyy hh.mm.ss");
    }

    protected void InvokeCopyCompletedEvent(string resultDescription) {
        if (CopyingCompletedEvent != null)
            CopyingCompletedEvent(resultDescription);
    }

    protected void InvokeUpdateViewState() {
        if (UpdateViewState != null)
            UpdateViewState();
    }

    protected DriveInfo GetFirstReadyRemovableDrive() {
        return
            DriveInfo.GetDrives()
                     .FirstOrDefault(driveInfo => driveInfo.DriveType == DriveType.Removable && driveInfo.IsReady);
    }

    public void Copy() {
        filesCopier.Copy();
    }
}

public interface IFilesCopier {
    void Copy();
}

public class KFilesCopier : FilesCopyingModel, IFilesCopier {
    private string destinationKFilesDirPath;

    public new void Copy() {
       //some code
    }

    private static string ComposeDestinationKFilesDirPath(DriveInfo drive) {
        //some code
    }
}

public class LogsDirCopier : FilesCopyingModel, IFilesCopier {
    public readonly string LogsDirPath;

    public LogsDirCopier() {
        //some code
    }

    public new void Copy() {
        //some code
    }

    private void InternalCopyLogsDir(string destinationPath) {
       //some code
    }

    private static void CloseStorer(ZipStorer zipStorer) {
        //some code
    }

    private static string ComposeDestinationArchiveFilePath(string destinationPath) {
        //some code
    }

    private void DetermineLogFilesCount() {
        //some code
    }
ViewModel与上面的基础结构交互如下:

interface ILongRunningTask {
    void DoWork();
}
public class FilesCopyingViewModel: Screen {       
    private readonly FilesCopyingModel model;
    private readonly IWindowManager windowManager;

    public int CurrentProgress {
        get { return model.CurrentProgressValue; }
    }

    public int FilesCountToCopy {
        get { return model.FilesCountToCopy; }
    }

    [ImportingConstructor]
    public LongRunningViewModel(IFilesCopier copier) {
        model = copier as FilesCopyingModel;
        model.CopyingCompletedEvent += CopyingCompletedHandler;
        model.UpdateViewState += UpdateViewStateHandler;
        windowManager = new WindowManager();
    }

    private void UpdateViewStateHandler() {
        NotifyOfPropertyChange(() => CurrentProgress);
        NotifyOfPropertyChange(() => FilesCountToCopy);
    }

    private void CopyingCompletedHandler(string resultDescription) {
        //some code
    }

    private void RemoveDriveSafely() {
        //some code
    }

    private void PromptEjection(string result) {
        //some code
    }

    private void PromptSuccessEjection() {
        //some code
    }

    private void PromptEjectFlashError() {
        //some code
    }

    protected override void OnActivate() {
        try {
            var copier = (IFilesCopier) model;
            Task.Factory.StartNew(copier.Copy);
        }
        catch (Exception ex) {
            //error handling
        }
    }
}

这两个类使用“Copy”作为方法的名称。现在我想再添加一个行为非常相似的类,但它的方法应该命名为“CollectDiagnosticInfo”。或者我可以添加一个类DiagnosticInfoCopier:IFilesCopier,然后做同样的事情。我真的不知道,但第六感表明有某种气味。

嗯,听起来有点奇怪。例如,当计数器更改时,模型调用UpdateViewState。-为什么模型应该有这样的方法或功能?如果您将根据MVVM模式实现它,VM将包含它。模型应该尽可能地保持愚蠢。您可以显示您的模型类和VM类吗?您的
ViewModel
应该对视图进行理想的建模。那么您的视图是否包含所有3个操作?如果是这样,请制作3份
模型的副本
,并将其放置在ViewModel的属性中。或者一次只能运行一个长期运行的任务?如果是这样的话,那么只需要一份
LongRunningTaskModel
的副本,并根据用户正在执行的操作填充其数据。