0
votes

I want to change value of ViewModel property (which is binded with DataContext). Extremely easy with classic Events, with Commands it becomes formidable task. This is my code:

public partial class MainWindow : Window
    {
        ViewModel _vm = new ViewModel();
        public MainWindow()
        {
            InitializeComponent();

            _vm.BtnClick = new BtnClick();

            DataContext = _vm;
        }
    }

public class BtnClick : ICommand
    {
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

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

        public void Execute(object parameter)
        {
            Debug.WriteLine(parameter.ToString());
        }
    }

public class ViewModel
    {
        public ICommand BtnClick { get; set; }
        public string Input { get; set; }
        public string Output { get; set; }
    }
<StackPanel>
        <TextBox Text="{Binding Input}"></TextBox>
        <TextBlock Text="{Binding Output}"></TextBlock>
        <Button Command="{Binding Path=BtnClick}" CommandParameter="{Binding Input}">Translate</Button>
    </StackPanel>

Command properly takes value from TextBox, now i want to do things with this value and save it to Output. And problem is from Command perspective i cannot access both DataContext and ViewModel.

1
What makes you think you need access to the DataContext? What's the problem you're trying to solve? The Command instance should really be defind in your ViewModel, not in the View.Peregrine
In order to change TextBlock Text, i have to access ViewModel. There is no other way.AdmiralCat3
The whole point of MVVM is that you do all updates through ViewModel properties and the corresponding UI controls will be updated via data binding. This does require that your ViewModel implements INotifyPropertyChanged though.Peregrine

1 Answers

0
votes

The implementation of any command is usually in a viewmodel.

A framework or helper class is routinely used.

For example:

https://riptutorial.com/mvvm-light/example/32335/relaycommand

public class MyViewModel { .....

public ICommand MyCommand => new RelayCommand(
   () =>
  {
    //execute action
    Message = "clicked Button";
  },
  () =>
  {
    //return true if button should be enabled or not
    return true;
  }

);

Here, there is an anonymous method with that "clicked button" in it.

This will capture variables in the parent viewmodel.

You may therefore set a public property in the viewmodel that's bound to the text property in your view.

For the view to respond you will need to implement inotifypropertychanged and raise property changed in the setter of that public property.

https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification.

From the above.

If PersonName was bound to a textblock in the view.

  public string PersonName
  {
      get { return name; }
      set
      {
          name = value;
          // Call OnPropertyChanged whenever the property is updated
          OnPropertyChanged();
      }
  }

In the command you can do:

 PersonName = "Andy";

Which calls the setter of PersonName and a textblock bound to PersonName will read the new value.