我使用 MVVM 模式 向窗口中的用户控件提供数据。
我想实现一个 View 模型上的方法 的对象转接任何来电到对应用户控件 ,它提供数据。为此,我需要一个 引用控件在 View 模型对象中。
我可以通过在用户控件上声明一个返回对控件本身的引用的属性来做到这一点,然后绑定(bind)到 View 模型对象,但这很丑:
<MyUserControl ReferenceToMyself="{Binding CorrespondingUserControl, Mode=OneWayToSource}"/>
然后在 View 模型对象中:
public void MethodThatForwardsCalls() => CorrespondingUserControl.ThisIsCalled();
有没有更好的方法将控件本身绑定(bind)到 View 模型对象 ?
最佳答案
您是否考虑过在 ViewModel 和 View 之间使用类似事件的交互来避免在 ViewModel 中保留对 View 的引用?
在 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
, 添加事件回调到 DataContextChanged
事件;this.DataContextChanged += MyUserControl_DataContextChanged;
在 CS 构造函数中,或DataContextChanged="MyUserControl_DataContextChanged"
在 XAML 构造函数中。现在,在事件回调中,您可以设置
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,调用您只需将方法的主体更改为;
public void MethodThatForwardsCalls()
{
this.ThisIsCalledEvent?.Invoke(); //Invoke the Action, if it exists, that has been set by the View
}
这样,您永远不会在 ViewModel 中保留 View 的实例,并且每次从 ViewModel 实例化新 View 时,它都会设置
Action
打回来。编辑
正如 Jürgen Röhr 在评论中所建议的,在
DataContextChanged
中事件回调,可以使用args.NewValue
绑定(bind)到新的 DataContext。此外,如果您将代理注册到 Action
除了设置属性之外,您还可以使用 args.OldValue
从以前的 DataContext 中注销它。
关于c# - 将 WPF 元素本身绑定(bind)到 View 模型对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51795917/