How to open a new window using MVVM Light Toolkit

后端 未结 6 865
青春惊慌失措
青春惊慌失措 2020-11-27 11:50

I am using MVVM Light toolkit in my WPF application. I would like to know what is the best approach for opening a new window from an existing window. I have got this M

相关标签:
6条回答
  • 2020-11-27 12:09

    I find the best way to approach this, is opening and closing the window from the ViewModel. As this link suggests,

    1. Create a DialogCloser class
        public static class DialogCloser
        {
            public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached("DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged));
    
            private static void DialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var window = d as Window;
                if (window != null) window.Close();
            }
    
            public static void SetDialogResult(Window target, bool? value)
            {
                target.SetValue(DialogResultProperty, value);
            }
        }
    
    1. Create a Base ViewModel inheriting from GalaSoft.MvvmLight.ViewModelBase with there additional members. Once done, use this viewmodel as base for other viewmodels.
        bool? _closeWindowFlag;
        public bool? CloseWindowFlag
        {
            get { return _closeWindowFlag; }
            set
            {
                _closeWindowFlag = value;
                RaisePropertyChanged("CloseWindowFlag");
            }
        }
    
        public virtual void CloseWindow(bool? result = true)
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
            new Action(() =>
            {
                CloseWindowFlag = CloseWindowFlag == null ? true : !CloseWindowFlag;
            }));
        }
    1. In the view, Bind the DialogCloser.DialogResult dependency property with the CloseWindowFlag property in the base viewmodel.

    Then you can open/close/hide the window from the viewmodel.

    0 讨论(0)
  • 2020-11-27 12:11

    Why do you go this route? Its simple. If you replace your button with a toggleButton, or a hyperlink, or any other number of button-like controls, you don't need to update your "code behind" - its a basic principle of the MVVM pattern. In your new toggleButton (or whatever), you still end up binding to the same exact Command.

    For example, I'm creating a project for a client who wants to have 2 UI's - one is going to be fundamentally different in every way, in terms of presentation. Horizontal tabs vs Vertical RadPanelBar (think Accordion) for navigation. Both of these views can point to the same viewModel - when a user clicks the Work Order tab in View 1, it fires the same "WorkOrderCommand" that's fired in the Work Order Header in the panel bar.

    In a code-behind model, you'd have to code two separate events. Here you only have to code one.

    Furthermore, it allows a designer using Blend to create any layout they want. As long as they have the hooks (EventToCommand control) in place, myself (as a developer) couldn't care less what the final product looks like.

    Loose coupling is incredibly powerful.

    0 讨论(0)
  • 2020-11-27 12:17

    Passing a message from ViewModel1 to View1 means to use the messaging capabilities in the MVVM Light Toolkit.

    For example, your ViewModel1 could have a command called ShowView2Command, then it would send a message to display the view.

    public class ViewModel1 : ViewModelBase
    {
        public RelayCommand ShowView2Command { private set; get; }
    
        public ViewModel1() : base()
        {
            ShowView2Command = new RelayCommand(ShowView2CommandExecute);
        }
    
        public void ShowView2CommandExecute()
        {
            Messenger.Default.Send(new NotificationMessage("ShowView2"));
        }
    }
    

    View1 would register to receive messages in its code behind and display View2 when it receives the correct message.

    public partial class View1 : UserControl
    {
        public View1()
        {
            InitializeComponent();
            Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
        }
    
        private void NotificationMessageReceived(NotificationMessage msg)
        {
            if (msg.Notification == "ShowView2")
            {
                var view2 = new view2();
                view2.Show();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 12:28

    Unless I am missing the point here - if I were to use the code behind, then why not directly implement button_click event and open the second view?

    What Bugnion seems to be suggesting is view1 -> button click -> relay command -> viewmodel1 -> message -> view1 -> view1.cs -> open view 2.

    You are going to sacrifice testability anyhow by writing code-behind, so why take such a long route?

    0 讨论(0)
  • 2020-11-27 12:32

    You can abstract the view specific features into services using generic interface. In the view layer you can provide concrete instances of these services and build view models using the IoC container and Dependency Injection technique.

    In your case you can build an interface IWindowManager or something similar which has the required method. This can be implmented in your view layer. I wrote a small blog post recently demonstrating how to abstract the dialog behaviour out of view model. Similar apporach can be used for any user interface related service like Navigation, MessageBoxes etc.

    This link might be helpful for you http://nileshgule.blogspot.com/2011/05/silverlight-use-dialogservice-to.html

    Many people also use the approach of firing events from view models which are subscribed on the view.cs file and from there the MessageBox or any other UI related action is performed. I personally like the approach of injecting services because then you can provide multiple implementations of the same service. A simple example would be how navigation is handled in Silverlight and Windows Phone 7 applications. You can use the same view model but inject different implementations of the Navigation service based on the application type.

    0 讨论(0)
  • 2020-11-27 12:35

    You can do in this way like you need to create some events and register those in view and call these in view model.and open that pop up window.

    Like This example

    public class Mainclass : MainView
    {
        public delegate abc RegisterPopUp(abc A);
        public RegisterPopUp POpUpEvent ;
    
        public RelayCommand ShowCommand { private set; get; }  
    
    
        public void ShowCommand() 
        { 
            ShowCommand("Your parameter");
        } 
    }
    

    inside the view MainView mn=new MainView();

    Register the event here like thake mn.POpUpEvent += than click on tab button double time

    and in registers popup method right the code for opening the pop up window.

    0 讨论(0)
提交回复
热议问题