开发者

WPF: How to call function of a custom UserControl in the ViewModel

开发者 https://www.devze.com 2023-02-10 16:11 出处:网络
I have a custom control defined using WPF in a independent assembly. In another project, I simply just reference it and use it in the XAML like this:

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

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

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

I used to call this function inside View.xaml开发者_开发问答.cs file using:

myControl.Reset()

However, for a valid reason, I have to move the logic of calling this function into the ViewModel. As far as I know, it is not a good practice to have a reference to the view in the ViewModel. Therefore I won't be able to access the "myControl" reference from the ViewModel.

My question is: How can I call the Reset function within the ViewModel.

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

Many thanks.


In the past I have hooked up the event from within the View's code-behind.

ViewModel:

public ICommand ResetCommand {get; set;}

From UserControl's 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());
}


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

using System.Windows.Input;

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

Have your base View Model implement this interface, e.g.

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

And Rachel's 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 could be used to decorate any number of view models, and the interface can be defined in the same library as the UserControl. In the main ViewModel, you'd simply do something like ResetCommand.Execute(this) or whatever param you'd like to pass.

0

精彩评论

暂无评论...
验证码 换一张
取 消