您能否更具体地说明条件是什么? @ColineE 和 @ChrisBD 正确地指出 ICommands 和 EventTocommandBehavior 在许多情况下都会有所帮助,例如将按钮单击或鼠标悬停事件转换为 ViewModel 中的方法调用。 如果可以使用这些方法,我会提倡使用它们,因为它们被认为是最佳实践
但是,有些情况需要比这更复杂的东西。一种解决方案是使用代码隐藏将 DataContext 转换为视图模型类型并直接调用该方法。例如:
// Inside MyViewModel.cs
public class MyViewModel : INotifyPropertyChanged
{
// ...
}
// ...
// Inside MyControl.xaml.cs
public class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
pubilc void OnSomeConditionMatches()
{
var myViewModel = DataContext as MyViewModel;
if (myViewModel != null)
{
// Hacky, but it works
myViewModel.CallCustomMethod();
}
}
}
这被认为有点 hacky,并且会在运行时使用 ViewModel 类型的知识污染代码隐藏。我们想要避免的事情,因为它打破了 View 和 ViewModel 之间的关注点分离。
另一种方法是我自己在处理很少或没有数据绑定支持的自定义控件时使用的方法。通过使用视图上的接口和附加属性,您可以inject a view instance into the viewModel and manipulate it directly。一种混合 MVVM / MVP 模式,我创造了 MiVVM。
UML
Xaml:
<!-- Assumes myViewModel is the viewmodel we are binding to -->
<!-- which has property InjectedUserControl of type IMyControl -->
<Example3:MyControl DataContext="{StaticResource myViewModel}"
Injector.InjectThisInto="InjectedUserControl">
</Example3:MyControl>
代码:
// Defines an interface to the usercontrol to
// manipulate directly from ViewModel
public interface IMyControl
{
// Our test method to call
void CallView(string message);
}
// Defines the usercontrol
public partial class MyControl : UserControl, IMyControl
{
public MyControl()
{
InitializeComponent();
}
public void CallView(string message)
{
MessageBox.Show(message);
}
}
public class MyViewModel
{
private IMyControl myControl;
public IMyControl InjectedUserControl
{
set
{
Debug.WriteLine(string.Format("Received Injected Control \"{0}\"",
value == null ? "NULL" : value.GetType().Name));
this.myControl = value;
this.OnInjectedObjectsChanged();
}
}
private void OnInjectedObjectsChanged()
{
// Directly access the view via its interface
if (this.myControl != null)
this.myControl.CallView("Hello From MyViewModel");
}
}
有关包含 Injector 附加属性源的可下载演示,请参阅this blog 帖子。还有this previous question,这是相关的。
最好的问候,