WPF:如何在ViewModel中调用自定义UserControl的功能

时间:2011-02-14 18:12:58

标签: wpf controls viewmodel

我在独立程序集中使用WPF定义了自定义控件。在另一个项目中,我只是引用它并在XAML中使用它,如下所示:

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

CustomUserControl类有一个名为“Reset”的成员函数。

我曾经使用以下方法在View.xaml.cs文件中调用此函数:

myControl.Reset()

但是,出于正当理由,我必须将调用此函数的逻辑移到ViewModel中。据我所知,在ViewModel中引用视图并不是一个好习惯。因此,我将无法从ViewModel访问“myControl”引用。

我的问题是:如何在ViewModel中调用Reset函数。

这是一个常见的用例,我相信有一种方法可以做到这一点。有人能指出我正确的方向。

非常感谢。

2 个答案:

答案 0 :(得分:3)

在过去,我已经从View的代码隐藏中吸引了这个事件。

视图模型:

public ICommand ResetCommand {get; set;}

来自UserControl的OnLoad方法:

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());
}

答案 1 :(得分:1)

@Rachel的解决方案很棒。使用界面可以使它更松散地耦合:

using System.Windows.Input;

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

让您的基本视图模型实现此接口,例如

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

Rachel的代码变成:

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));
}

此接口可用于装饰任意数量的视图模型,并且可以在与UserControl相同的库中定义接口。在主ViewModel中,您只需执行类似ResetCommand.Execute(this)或您希望传递的任何参数的内容。