简体   繁体   English

WPF MVVM应用程序的设计

[英]Designs of a WPF MVVM Application

I have been doing tons of research using MVVM (Model View ViewModel) with WPF. 我一直在使用带有WPF的MVVM(模型视图ViewModel)进行大量研究。 I am developing a desktop application. 我正在开发桌面应用程序。 This application consists of a main window. 该应用程序包含一个主窗口。 This main window has some buttons which do something. 这个主窗口有一些可以做一些事情的按钮。 Also, there is a button that opens a OpenFileDialog box. 另外,还有一个按钮可以打开OpenFileDialog框。

Currently, this is my ViewModel to which the main window binds to: 当前,这是主窗口绑定到的我的ViewModel:

MainWindowPresenter Class

namespace BMSVM_Simulator.ViewModel
{
    class MainWindowPresenter : ObservableObject
    {
        private bool logLoaded; // true if a log is currently loaded, false otherwise

        public MainWindowPresenter()
        {
            logLoaded = true;
        }

        public ICommand load_data_button_pressed
        {
            get { return new DelegateCommand(doLoadData);  }
        }

        private void doLoadData()
        {
            // DO LOAD DATA COMMANDS
        }

        public ICommand exit_button_pressed
        {
            get { return new DelegateCommand(doExit); }
        }

        private void doExit()
        {
            // DO EXIT COMMANDS
        }
    }
}

QUESTION 1 : I am concerned that this is the "wrong" implementation. 问题1 :我担心这是“错误”的实现。 Is it correct (per MVVM) for each button to have a property of type ICommand and then a corresponding method implementing the functionality? 每个按钮具有ICommand类型的属性,然后具有实现该功能的相应方法,是否正确(针对MVVM)? A main window with a lot of buttons would have a very large ViewModel class, no? 一个带有很多按钮的主窗口会有一个非常大的ViewModel类,不是吗?

QUESTION 2 : If one of the buttons was a File->Open File button. 问题2 :如果按钮之一是“文件”->“打开文件”按钮。 So, in that case it would open up a new OpenFileDialog window. 因此,在这种情况下,它将打开一个新的OpenFileDialog窗口。 Would this be done in the same way I previously done it above (ie have a public ICommand open_file_dialog_button_pressed property and a corresponding public void doOpenFileDialog() method? This seems like I am mixing the "view" of the open file dialog into the ViewModel, although the view is already defined by the built in wpf OpenFileDialog class. 是否可以按照我之前做的相同方式(例如,有一个public ICommand open_file_dialog_button_pressed属性和一个相应的public void doOpenFileDialog()方法? public void doOpenFileDialog()似乎是我将打开文件对话框的“视图”混入了ViewModel中,尽管该视图已经由内置的wpf OpenFileDialog类定义。

QUESTION 3 : Is it true that each "view" of our application should have only a single "presenter" class (which is part of the ViewModel) to which that view binds to? 问题3:这是真的,我们的每一个应用程序的“视图”应该只有一个单一的 “演讲者”类(这是视图模型的一部分)是该视图结合? In the example above, my main window view binds to only the MainWindowPresenter class. 在上面的示例中,我的主窗口视图绑定到MainWindowPresenter类。 If I were to make another view (say a graph generated with Microsoft's Dynamic Data Display library in it's own popout window), I would need an additional "presenter" class in my ViewModel, correct? 如果要进行其他视图(例如使用在其自己的弹出窗口中使用Microsoft动态数据显示库生成的图形),则在ViewModel中需要一个附加的“ presenter”类,对吗?

Thank you very much! 非常感谢你! Rich 丰富

For reference, I've included these classes, but they may not be useful: 作为参考,我包括了这些类,但是它们可能没有用:

DelegateCommand Class DelegateCommand类别

namespace BMSVM_Simulator.ViewModel
{
    public class DelegateCommand : ICommand
    {
        private readonly Action _action;

        public DelegateCommand(Action action)
        {
            _action = action;
        }

        public void Execute(object parameter)
        {
            _action();
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

#pragma warning disable 67
        public event EventHandler CanExecuteChanged;
#pragma warning restore 67
    }
}

ObservableObject Class ObservableObject

namespace BMSVM_Simulator.ViewModel
{
    class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        //basic ViewModelBase
        internal void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
        }
    }
}

1) Yes that's correct. 1)是的,这是正确的。 You need to create a command property for each command. 您需要为每个命令创建一个命令属性。 But thanks to your relay command you don't need to implement it directly. 但是由于您的中继命令,您不需要直接实现它。 To prevent your ViewModel from busting i would recommend to move all commands into a separate CommandsViewModel serving as command source. 为了防止ViewModel崩溃,我建议将所有命令移到单独的CommandsViewModel中作为命令源。 Your View then binds to it. 然后,您的视图将绑定到它。

2) Opening the Dialog can be achieved in XAML via routed commands using the CommandBinding property. 2)可以使用CommandBinding属性通过路由命令在XAML中实现打开对话框。 So the tasks remains in the view. 因此,任务仍保留在视图中。 You basically try to avoid the dependency on any view related object. 您基本上试图避免依赖于任何与视图相关的对象。 .NET provides some ready to use commands for common purposes ( MSDN - ApplicationCommands ) .NET提供了一些现成的常用命令( MSDN-ApplicationCommands

3) You can share ViewModels among Views of course. 3)您当然可以在视图之间共享ViewModels。 That's one reason you structure your implementation into Model View ViewModel to be independent from changes and for reusability. 这是您将实现结构化为Model View ViewModel的原因之一,以使其与更改无关并具有可重用性。 It can become critical when more than one view is updating the same source simultaneously. 当多个视图同时更新同一源时,它可能变得至关重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM