我使用 MVVM模式将数据提供给窗口中的用户控件。 我想在视图模型上实现一个方法对象,该对象将任何调用转发给相应的用户控件,该控件随数据一起提供。为此,我需要在视图模型对象中具有对控件的引用。
我可以通过在用户控件上声明一个属性来做到这一点,该属性返回对控件本身的引用,然后绑定到视图模型对象,但这很丑陋:
<MyUserControl ReferenceToMyself="{Binding CorrespondingUserControl, Mode=OneWayToSource}"/>
然后在视图模型对象中:
public void MethodThatForwardsCalls() => CorrespondingUserControl.ThisIsCalled();
是否有更好的方法将控件本身绑定到视图模型对象?
答案 0 :(得分:2)
您是否考虑过在ViewModel和View之间使用类似事件的交互方式,以避免必须将View的引用保留在ViewModel中?
在ViewModel中,我将创建类型为Action
的属性,并将其命名为ThisIsCalledEvent
;
#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
的{{1}}事件中添加事件回调;
DataContextChanged
在CS构造函数中,或者
this.DataContextChanged += MyUserControl_DataContextChanged;
在XAML构造函数中。
现在,在事件回调中,您可以为ViewModel的DataContextChanged="MyUserControl_DataContextChanged"
属性设置Action
;
ThisIsCalledEvent
现在,回到ViewModel,只需将方法的主体更改为即可调用您
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中保留View的实例,并且每次从ViewModel实例化新视图时,它都会设置public void MethodThatForwardsCalls()
{
this.ThisIsCalledEvent?.Invoke(); //Invoke the Action, if it exists, that has been set by the View
}
回调。
编辑
正如JürgenRöhr在评论中所建议的那样,在Action
事件回调中,可以使用DataContextChanged
绑定到新的DataContext。此外,如果您另外将委托注册到args.NewValue
属性中而不是对其进行设置,则可以使用Action
从先前的DataContext中注销它。