C# 将WPF元素本身绑定到视图模型对象

C# 将WPF元素本身绑定到视图模型对象,c#,wpf,xaml,mvvm,data-binding,C#,Wpf,Xaml,Mvvm,Data Binding,我使用MVVM模式向窗口中的用户控件提供数据。 我想在视图模型对象上实现一个方法,该方法将所有调用转发给它自己,并将其与数据一起提供给相应的用户控件。为此,我需要对视图模型对象中的控件进行引用 我可以通过在用户控件上声明一个属性来实现这一点,该属性返回对控件本身的引用,然后绑定到视图模型对象,但它非常难看: <MyUserControl ReferenceToMyself="{Binding CorrespondingUserControl, Mode=OneWayToSource}"/&

我使用MVVM模式向窗口中的用户控件提供数据。 我想在视图模型对象上实现一个方法,该方法将所有调用转发给它自己,并将其与数据一起提供给相应的用户控件。为此,我需要对视图模型对象中的控件进行引用

我可以通过在用户控件上声明一个属性来实现这一点,该属性返回对控件本身的引用,然后绑定到视图模型对象,但它非常难看:

<MyUserControl ReferenceToMyself="{Binding CorrespondingUserControl, Mode=OneWayToSource}"/>

是否有更好的方法将控件本身绑定到视图模型对象上?

您是否考虑过在视图模型和视图之间使用类似事件的交互,以避免在视图模型中保留视图的引用

在ViewModel中,我将创建一个类型为
Action
的属性,并将其命名为类似
ThiisCalledEvent

#region ThisIsCalledEvent
        private Action m_ThisIsCalledEvent;
        public Action ThisIsCalledEvent
        {
            get
            {
                return m_ThisIsCalledEvent;
            }
            set
            {
                if (m_ThisIsCalledEvent != value)
                {
                    m_ThisIsCalledEvent = value;
                    OnPropertyChanged(nameof(ThisIsCalledEvent));
                }
            }
        }

#endregion
然后,在
MyUserControl
中,向
DataContextChanged
事件添加事件回调

this.DataContextChanged+=MyUserControl\u DataContextChanged,或
XAML构造函数中的
DataContextChanged=“MyUserControl\u DataContextChanged”

现在,在事件回调中,您可以为ViewModel的
thiiscalledevent
属性设置
Action

private void MyUserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    MyUserControlViewModel vm = DataContext as MyUserControlViewModel; //Get the ViewModel from the View's DataContext

    if(vm == null)
        return;

    vm.ThisIsCalledEvent = delegate () { ThisIsCalled(); }; //When the action is invoked, call the desired function
}
现在,回到ViewModel,要调用它,只需将方法的主体更改为

public void MethodThatForwardsCalls()
{
    this.ThisIsCalledEvent?.Invoke(); //Invoke the Action, if it exists, that has been set by the View
}
这样,您就不会在ViewModel中保留视图的实例,每次从ViewModel实例化新视图时,它都会设置
操作
回调

编辑
正如Jürgen Röhr在评论中所建议的,在
DataContextChanged
事件回调中,您可以使用
args.NewValue
绑定到新的DataContext。此外,如果您另外将委托注册到
操作
属性,而不是将其设置,您可以使用
args.OldValue
将其从以前的DataContext中注销。

您是否考虑过在ViewModel和视图之间使用类似事件的交互,以避免在ViewModel中保留视图的引用

在ViewModel中,我将创建一个类型为
Action
的属性,并将其命名为类似
ThiisCalledEvent

#region ThisIsCalledEvent
        private Action m_ThisIsCalledEvent;
        public Action ThisIsCalledEvent
        {
            get
            {
                return m_ThisIsCalledEvent;
            }
            set
            {
                if (m_ThisIsCalledEvent != value)
                {
                    m_ThisIsCalledEvent = value;
                    OnPropertyChanged(nameof(ThisIsCalledEvent));
                }
            }
        }

#endregion
然后,在
MyUserControl
中,向
DataContextChanged
事件添加事件回调

this.DataContextChanged+=MyUserControl\u DataContextChanged,或
XAML构造函数中的
DataContextChanged=“MyUserControl\u DataContextChanged”

现在,在事件回调中,您可以为ViewModel的
thiiscalledevent
属性设置
Action

private void MyUserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    MyUserControlViewModel vm = DataContext as MyUserControlViewModel; //Get the ViewModel from the View's DataContext

    if(vm == null)
        return;

    vm.ThisIsCalledEvent = delegate () { ThisIsCalled(); }; //When the action is invoked, call the desired function
}
现在,回到ViewModel,要调用它,只需将方法的主体更改为

public void MethodThatForwardsCalls()
{
    this.ThisIsCalledEvent?.Invoke(); //Invoke the Action, if it exists, that has been set by the View
}
这样,您就不会在ViewModel中保留视图的实例,每次从ViewModel实例化新视图时,它都会设置
操作
回调

编辑
正如Jürgen Röhr在评论中所建议的,在
DataContextChanged
事件回调中,您可以使用
args.NewValue
绑定到新的DataContext。此外,如果您另外将委托注册到
操作
属性而不是设置它,则可以使用
args.OldValue
将其从以前的数据上下文中注销。

好的。只需使用
MyUserControl\u DataContextChanged
中的
args
参数注册到
NewValue。这是calledevent
并从'OldValue.Thiiscalledevent'注销。Mark Diederick谢谢,此解决方案肯定能解决问题。实际上slugster在回答中提到的事件聚合器模式是一种更优雅的方法,对于我的案例,我发现这种解决方法很有用。@JürgenRöhr感谢您的重要评论,这甚至不仅仅是一件微妙的事情,args.OldValue对于取消订阅事件非常有用,这样可以防止内存泄漏的发生!好的。只需使用
MyUserControl\u DataContextChanged
中的
args
参数注册到
NewValue。这是calledevent
并从'OldValue.Thiiscalledevent'注销。Mark Diederick谢谢,此解决方案肯定能解决问题。实际上slugster在回答中提到的事件聚合器模式是一种更优雅的方法,对于我的案例,我发现这种解决方法很有用。@JürgenRöhr感谢您的重要评论,这甚至不仅仅是一件微妙的事情,args.OldValue对于取消订阅事件非常有用,这样可以防止内存泄漏的发生!不要那样做!如果您需要通知视图某件事或调用某个方法以响应别处发生的事件,请查看使用允许您发布和订阅事件的事件聚合器模式。@slugster谢谢,我到目前为止还没有听说过事件聚合器模式,值得一试!我不确定我将使用哪种解决方案,但这是一个有价值的信息,+1开始!不要那样做!如果您需要通知视图某件事或调用某个方法以响应别处发生的事件,请查看使用允许您发布和订阅事件的事件聚合器模式。@slugster谢谢,我到目前为止还没有听说过事件聚合器模式,值得一试!我不确定我将使用哪种解决方案,但这是一个有价值的信息,+1开始!