-2

How do events management work in WPF using MVVM pattern? Should i really avoid using a direct event management? EXAMPLE: is building a view like this:

<Grid>
    <Button Click="GO_Button_Click" Content="Go" Margin="39,143,503,250"/>
    <TextBox x:Name="outputFolder" Margin="321,182,35,211" Text="{Binding outputFolderPath}"/>
</Grid>

having a viewmodel like this:

using System.ComponentModel;
using System.Windows;

namespace FirstWpfApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        #region variables
        public string outputFolderPath { get; set; }
        #endregion

        #region events
        private void GO_Button_Click(object sender, RoutedEventArgs e)
        {
            outputFolderPath = "Some data";
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(outputFolderPath)));
        }

        #endregion

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Wouldn't i have a better implementation of MVVM pattern avoiding to call "GO_Button_Click" method from view?

Valiant
  • 88
  • 1
  • 10
steame
  • 61
  • 1
  • 6

2 Answers2

1

Your XAML should like below,

<Button Command="{Binding Button1Command}" Content="GO"/>

And the code in MainWindow.xaml.cs. Here MainVM is the name of the ViewModel.

    public partial class MainWindow : Window {
        MainVM _vm;
        public MainWindow() {
            InitializeComponent();
            _vm = new MainVM(); //Also you handle it by Singleton instance
            base.DataContext = _vm;
        } 
    }

Now let see how the MainVM look like,

    public class MainVM : INotifyPropertyChanged {
        public DelegateCommand Button1Command { get; set; }
        public MainVM() {
            Button1Command = new DelegateCommand(onButton1Command);
        }
        private void onButton1Command(object obj) {
            //Your Code when Go button press
        }
        

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        protected Action<PropertyChangedEventArgs> RaisePropertyChanged() {
            return args => PropertyChanged?.Invoke(this, args);
        }

        #endregion
    }

Here is the DelegateCommand class that implement the ICommand interface,

public class DelegateCommand : ICommand {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _execute;

        public event EventHandler CanExecuteChanged;

        public DelegateCommand(Action<object> execute)
            : this(execute, null) {
        }

        public DelegateCommand(Action<object> execute,
                       Predicate<object> canExecute) {
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter) {
            if (_canExecute == null) {
                return true;
            }

            return _canExecute(parameter);
        }

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

        public void RaiseCanExecuteChanged() {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }
    }
Sayem
  • 131
  • 1
  • 1
  • 9
0

button has 'Command' Property, so you can binds it with a class which implement 'ICommand' interface. please check following docs. ICommand MVVM implementation.

and Plus, It seems like you use MainWindow as a DataContext, itself. this is not a MVVM ways. I think this way is just WPF binding practices. If you want to achieve MVVM part, first you should make ViewModel of window that represent an application domain knowledge and set DataContext of MainWindow to the ViewModel

Jeong Yo Han
  • 551
  • 4
  • 16