Implementing “close window” command with MVVM

后端 未结 12 1670
既然无缘
既然无缘 2020-12-05 09:31

So my first attempt did everything out of the code behind, and now I\'m trying to refactor my code to use the MVVM pattern, following the guidance of the MVVM in the box inf

相关标签:
12条回答
  • 2020-12-05 09:59

    I do it by creating a attached property called DialogResult:

    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 && (bool?)e.NewValue == true) 
                    window.Close();
        }
    
        public static void SetDialogResult(Window target, bool? value)
        {
            target.SetValue(DialogResultProperty, value);
        }
    }
    

    then write this to you XAML, in the window tag

    WindowActions:DialogCloser.DialogResult="{Binding Close}"
    

    finally in the ViewModel

        private bool _close;
        public bool Close
        {
            get { return _close; }
            set
            {
                if (_close == value)
                    return;
                _close = value;
                NotifyPropertyChanged("Close");
            }
        }
    

    if you change the Close to true, the window will be closed

    Close = True;
    
    0 讨论(0)
  • 2020-12-05 10:00

    This is taken from ken2k answer (thanks!), just adding the CloseCommand also to the base CloseableViewModel.

    public class CloseableViewModel
    {
        public CloseableViewModel()
        {
            CloseCommand = new RelayCommand(this.OnClosingRequest);
        }
    
        public event EventHandler ClosingRequest;
    
        protected void OnClosingRequest()
        {
            if (this.ClosingRequest != null)
            {
                this.ClosingRequest(this, EventArgs.Empty);
            }
        }
    
        public RelayCommand CloseCommand
        {
            get;
            private set;
        }
    }
    

    Your view model, inherits it

    public class MyViewModel : CloseableViewModel
    

    Then on you view

    public MyView()
    {
        var viewModel = new StudyDataStructureViewModel(studyId);
        this.DataContext = viewModel;
    
        //InitializeComponent(); ...
    
        viewModel.ClosingRequest += (sender, e) => this.Close();
    }
    
    0 讨论(0)
  • 2020-12-05 10:03

    MVVM-light with a custom message notification to avoid the window to process every notificationmessage

    In the viewmodel:

    public class CloseDialogMessage : NotificationMessage
    {
        public CloseDialogMessage(object sender) : base(sender, "") { }
    }
    
    private void OnClose()
    {
        Messenger.Default.Send(new CloseDialogMessage(this));
    }
    

    Register the message in the window constructor:

    Messenger.Default.Register<CloseDialogMessage>(this, nm =>
    {
        Close();
    });
    
    0 讨论(0)
  • 2020-12-05 10:04

    This solution is quick and easy. Downside is that there is some coupling between the layers.

    In your viewmodel:

    public class MyWindowViewModel: ViewModelBase
    {
    
    
        public Command.StandardCommand CloseCommand
        {
            get
            {
                return new Command.StandardCommand(Close);
            }
        }
        public void Close()
        {
            foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
            {
                if (window.DataContext == this)
                {
                    window.Close();
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 10:05

    using MVVM-light toolkit:

    In the ViewModel:

     public void notifyWindowToClose()
    {
        Messenger.Default.Send<NotificationMessage>(
            new NotificationMessage(this, "CloseWindowsBoundToMe")
        );
    }
    

    And in the View:

     Messenger.Default.Register<NotificationMessage>(this, (nm) =>
    {
        if (nm.Notification == "CloseWindowsBoundToMe")
        {
            if (nm.Sender == this.DataContext)
                this.Close();
        }
    });
    
    0 讨论(0)
  • 2020-12-05 10:07

    My solution to close a window from view model while clicking a button is as follows:

    In view model

    public RelayCommand CloseWindow;
    Constructor()
    {
        CloseWindow = new RelayCommand(CloseWin);
    }
    
    public void CloseWin(object obj)
    {
        Window win = obj as Window;
        win.Close();
    }
    

    In View, set as follows

    <Button Command="{Binding CloseWindowCommand}" CommandParameter="{Binding ElementName=WindowNameTobeClose}" Content="Cancel" />
    
    0 讨论(0)
提交回复
热议问题