How can I avoid command clutter in the ViewModel?

ぐ巨炮叔叔 提交于 2019-12-30 06:20:10

问题


I am building an application that uses quite a few commands, and they are cluttering up my viewmodel. MVVM is new to me, so sorry if this question is a bit stupid. Is there a way to reduce the clutter? For example here you can see the a part of the clutter..

    private void InitializeCommands()
    {
        LogoutCommand = new RelayCommand(Logout);
        OpenCommand = new RelayCommand(SetImage);
        SaveCommand = new RelayCommand(SaveImage, SaveImageCanExecute);
        UploadToFlickrCommand = new RelayCommand(UploadToFlickr);
        CropCommand = new RelayCommand(SetCropMouseEvents);
        RemoveRedEyeCommand = new RelayCommand(SetRemoveRedEyeMouseEvents);
        TextInputCropCommand = new RelayCommand(CropFromText);
        ReloadImageCommand = new RelayCommand(ReloadImage);
        FlipYCommand = new RelayCommand(FlipY);
        Rotate90RCommand = new RelayCommand(Rotate90R);
        FlipXCommand = new RelayCommand(FlipX);
        ToGrayscaleCommand = new RelayCommand(ToGrayscale);
        ToSepiaCommand = new RelayCommand(ToSepia);
        WindowClosingCommand = new RelayCommand(WindowClosing);
        EffectsViewCommand = new RelayCommand(() => CurrentToolView = new EffectsView());
        AddTextCommand = new RelayCommand(() => CurrentToolView = new AddTextView());
        ResizeCommand = new RelayCommand(() => CurrentToolView = new ResizeView());
        CropViewCommand = new RelayCommand(() => CurrentToolView = new CropView());
        RedEyeCommand = new RelayCommand(() => CurrentToolView = new RedEyeView());
        RotateViewCommand = new RelayCommand(() => CurrentToolView = new RotateView());
        ExitCommand = new RelayCommand(() => Application.Current.Shutdown());
        FullscreenCommand = new RelayCommand(() =>
                                                 {
                                                     var fs = new FullscreenView
                                                                  {FullscreenImage = CurrentImage.LoadedImage};
                                                     fs.Show();
                                                 });
        HandleDropCommand = new RelayCommand<DragEventArgs>(e => OnFileDrop(this, e));
        Messenger.Default.Register<User>(this, "UserLogin", SetUser);
        Messenger.Default.Register<FlickrAccount>(this, "AddedAccount", AddAccount);
        Messenger.Default.Register<string>(this, "INeedAUser", SendUser);
        Messenger.Default.Register<string>(this, "INeedAImage", SendImage);
    }

回答1:


So you have commands for:

  1. File operations (Open, Save, Upload to Flicker)

  2. Window operations (Full screen, Close)

  3. Editing (Rotating, Resizing, Colour, etc)

Consider grouping (composing) related commands together in a custom class called for example FileCommands. Create a multi-level hierarchy if applicable. If you have a hierarchical menu in your view, You'll likely want similar Command Hierarchy.

Then, create one Controller per command group (for example FileController) and in the controller create method that will register the commands from the FileCommands group with the associated service.

See http://waf.codeplex.com/ sample applications (for example BookController.cs) for some ideas on how to actually implement Controller/ViewModel mapping. Note however that it's not exact same scenario (no breaking of Commands into groups).




回答2:


Use Caliburn Micro. For a button named name="Logout" the only thing needed in the ViewModel is a public method named Logout.

And without convetion bindings:

<Button Content="Remove"
        cal:Message.Attach="[Event Click] = [Action Remove($dataContext)]" />

Then on the ViewModel add a method named Remove and in that sample the DataContext is passed to the method.




回答3:


Your ViewModel is meant to be the glue between the View and the Model. This implies that, unless you can generically iterate the Model, it will always consist of an enumeration of 'glue-lines'.

The only clutter I can imagine you could get rid of is in case you don't need the XXXCommand properties literally; in that case, you could create a collection of property-like, structures like (pseudo-code)

private void createCommands() {
   var commands={
      "Logout"=>new RelayCommand(Logout),
      "Exit"=>new RelayComand( ()=>Application.Current.Shutdown() ),
     ....
   };
   foreach( var key,cmd in commands ){
      glue(key,cmd);
   }
};

There's no other reason to keep references to the objects you create in here except for glueing them to the correct View binder.

But then again, why not use the Property idiom for this? Again: the amount of clutter, as I see it, is reasonably limited.



来源:https://stackoverflow.com/questions/8552566/how-can-i-avoid-command-clutter-in-the-viewmodel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!