WPF: how to call custom UserControl function in ViewModel

I have a custom control defined using WPF in an independent assembly. In another project, I just simply reference it and use it in XAML as follows:

<my:CustomUserControl Name="myControl" IsEnabled="{Binding CanTheUserInputTrade}"/>

The CustomUserControl class has a member function called "Reset".

I used this function in the View.xaml.cs file using:

myControl.Reset()

However, for good reason, I need to move the logic for calling this function to the ViewModel. As far as I know, it is not a good practice to have a view link in the ViewModel. Therefore, I will not be able to access the "myControl" link from the ViewModel.

My question is: how can I call the Reset function in the ViewModel.

This is a common use case, and I'm sure there is a way to do this. Can someone point me in the right direction.

Many thanks.

+3
source share
2 answers

In the past, I connected an event from the Code code.

ViewModel:

public ICommand ResetCommand {get; set;}

From the UserControl OnLoad method:

private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
{
    MyUserControl ctrl = sender as MyUserControl;
    if (ctrl == null) return;

    MyViewModel vm = ctrl.DataContext as MyViewModel ;

    if (vm == null)
        return;

    vm.ResetCommand = new RelayCommand(param => this.Reset());
}
+3
source

@Rachel's solution is excellent. Using an interface makes it more loosely coupled:

using System.Windows.Input;

namespace WpfApplication
{
    public interface IResetCaller
    {
        ICommand ResetCommand { get; set; }
    }
}

Ask the base view model to implement this interface, for example.

public class MyViewModel : ModelBase, IResetCaller
{
    ...
    public ICommand RefreshSegmentCommand { get; set; }
}

And the Rachel code becomes:

private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
{
    var ctrl = sender as FrameworkElement;
    if (ctrl == null) return;

    var vm = ctrl.DataContext as IResetCaller;

    if (vm == null)
        return;

    vm.ResetCommand = new RelayCommand(param => this.Reset(param));
}

This interface can be used to decorate any number of view models, and the interface can be defined in the same library as UserControl. In the main ViewModel, you simply do something like ResetCommand.Execute(this)or any other parameter that you want to pass.

+1
source

Source: https://habr.com/ru/post/1792063/


All Articles