【问题标题】:WPF: How to call function of a custom UserControl in the ViewModelWPF:如何在 ViewModel 中调用自定义 UserControl 的函数
【发布时间】:2011-02-14 18:12:57
【问题描述】:

我有一个使用 WPF 在独立程序集中定义的自定义控件。在另一个项目中,我只是简单地引用它并像这样在 XAML 中使用它:

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

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

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

myControl.Reset()

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

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

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

非常感谢。

【问题讨论】:

  • 什么时候需要调用这个reset方法?
  • 如果您想提供更多信息,请编辑您的问题。如果您的问题范围超出此范围,只需提出一个新问题即可。

标签: wpf controls viewmodel


【解决方案1】:

过去,我从 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());
}

【讨论】:

  • 嗨,Rachel,这是解决问题的好主意。但是,UserControl 是作为在许多地方使用的代码的公共部分编写的。放置硬编码的 DataContect -> MyViewModel 转换将使它们紧密耦合。有什么办法可以摆脱紧耦合?
  • 如果您的 UI 与其他 ViewModel 一起使用,则意味着某些东西在某个时候将两者联系在一起。无论做什么,都应该负责将 ViewModel.ResetCommand 连接到 View.Reset()
  • 你可以使用一个接口来使它更可重用。我将在下面发布一个完整的示例...
【解决方案2】:

@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) 之类的操作或您想要传递的任何参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    相关资源
    最近更新 更多