如何调用自定义控件';通过WPF中的一个命令调用

如何调用自定义控件';通过WPF中的一个命令调用,wpf,mvvm,Wpf,Mvvm,我正在使用自定义控件向用户显示三维渲染数据。该控件有一个ResetView()方法,该方法将控件的状态返回到其默认值。我有一个视图模型,它是窗口的数据上下文,因此,当在同一视图中单击按钮时,如何调用控件的ResetView方法并维护MVVM结构?我通常使用的一种可能方法: 在视图模型中创建IObservable类型的属性。你可以 使用被动扩展(RX)中的主题作为实际 实施 public class ViewModel { private Subject<Unit> _rese

我正在使用自定义控件向用户显示三维渲染数据。该控件有一个ResetView()方法,该方法将控件的状态返回到其默认值。我有一个视图模型,它是窗口的数据上下文,因此,当在同一视图中单击按钮时,如何调用控件的ResetView方法并维护MVVM结构?

我通常使用的一种可能方法:

在视图模型中创建IObservable类型的属性。你可以 使用被动扩展(RX)中的主题作为实际 实施

public class ViewModel
{
    private Subject<Unit> _resetRequest = new Subject<Unit>();

    public IObservable<Unit> ResetRequest
    {
        get { return _resetRequest; }
    }
}
公共类视图模型
{
私有主体_resetRequest=新主体();
公共IObservable重置请求
{
获取{return\u resetRequest;}
}
}
创建控件的行为。这种行为必须 绑定到您的属性并订阅可观察到的。打电话给你的 来自订阅OnNext处理程序的控件的ResetView()方法

public class ResetViewBehavior : Behavior<YourControl>
{
    private IDisposable _subscription;

    public static readonly DependencyProperty RequestProperty = DependencyProperty.Register("Request", typeof(IObservable<Unit>), typeof(ResetViewBehavior), new PropertyMetadata(null, OnRequestChanged));

    public IObservable<Unit> Request
    {
        get { return (IObservable<Unit>)GetValue(RequestProperty); }
        set { SetValue(RequestProperty, value); }
    }

    private static void OnRequestChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
         ((ResetViewBehavior)d).Resubscribe();
    }

    private void Resubscribe()
    {
        _subscription?.Dispose();
        _subscription = Request?.Subscribe(_ => AssociatedObject.ResetView());
    }

    protected override void OnAttached()
    {
        Resubscribe();
    }

    protected override void OnDetaching()
    {
        _subscription?.Dispose();
    }

}
公共类ResetViewBehavior:行为
{
私人IDisposable_订阅;
public static readonly dependencProperty RequestProperty=dependencProperty.Register(“请求”、typeof(IObservable)、typeof(ResetViewBehavior)、new PropertyMetadata(null、OnRequestChanged));
公共IObservable请求
{
获取{return(IObservable)GetValue(RequestProperty);}
set{SetValue(RequestProperty,value);}
}
请求更改时的私有静态无效(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
((ResetViewBehavior)d).重新订阅();
}
私人无效重新订阅()
{
_订阅?.Dispose();
_订阅=请求?.Subscribe(=>AssociatedObject.ResetView());
}
受保护的覆盖无效附加()
{
重新订阅();
}
附加时受保护的覆盖无效()
{
_订阅?.Dispose();
}
}
在XAML中:

   <Window>
        <YourControl>
            <i:Interaction.Behaviors>
                <b:ResetViewBehavior Request="{Binding ResetRequest}" />
            </i:Interaction.Behaviors>
        </YourControl>
    </Window>

要重置视图时,请从视图模型调用对象的OnNext方法

public class ViewModel
{
    private Subject<Unit> _resetRequest = new Subject<Unit>();

    public IObservable<Unit> ResetRequest
    {
        get { return _resetRequest; }
    }

    private void ResetView()
    {
        _resetRequest.OnNext(new Unit());
    }
}
公共类视图模型
{
私有主体_resetRequest=新主体();
公共IObservable重置请求
{
获取{return\u resetRequest;}
}
私有void ResetView()
{
_resetRequest.OnNext(新单元());
}
}
使用这种方法,您就不会有代码隐藏,就我个人而言,我一直试图在MVVM中避免这种情况。相反,您将逻辑包含在可重用行为中


如果使用其他类而不是单元作为IObservable参数,也可以将一些数据传递给控件的方法。

按钮。单击
控件。ResetView()
根本不涉及VM。您可以在代码隐藏中的单击处理程序中执行
control.ResetView()
,因为这是内部视图操作。第二种想法是,如果contol绑定到VM,VM可能应该具有
Reset
方法,并为按钮公开
ResetCommand
。命令绑定是的,我知道按钮单击不是MVVM,通过单击,我指的是绑定到按钮的命令nmvvm!=没有代码隐藏,也不意味着没有事件处理程序。UI关注点应该在UI中处理,而不是通过视图模型人工路由。视图模型应该接受用户输入(通过绑定和命令),解释它们,根据解释执行操作,然后用这些解释的结果更新它们的状态。他们不应该做任何UI工作。随着我变得更有经验,这就是我的想法。您认为从包含控件的用户控件的代码后面调用控件的方法是不好的做法吗?假设该方法调用不会影响呈现给用户的任何数据。非常感谢,我将研究如何实现它。