我需要将一个方法绑定到XAML文件中的自定义控件,而不是该方法的结果。
基本上,当满足某些条件时,自定义控件将触发该方法多次。
我该怎么做呢?
我在互联网上找到了一些解决方案,但大多数都是将方法的结果绑定到XAML中,这并不是我要找的解决办法。
非常感谢。
我需要将一个方法绑定到XAML文件中的自定义控件,而不是该方法的结果。
基本上,当满足某些条件时,自定义控件将触发该方法多次。
我该怎么做呢?
我在互联网上找到了一些解决方案,但大多数都是将方法的结果绑定到XAML中,这并不是我要找的解决办法。
非常感谢。
ICommand
的属性,将其绑定到 UI 元素的 Command 属性上。你能具体说明一下条件是什么吗?@ColineE和@ChrisBD正确指出,ICommands和EventTocommandBehavior在许多情况下都会有所帮助,例如将按钮单击或鼠标悬停事件转换为ViewModel中的方法调用。如果可以使用这些方法,我会建议使用它们,因为它们被认为是最佳实践
然而,有些情况需要比这更复杂的解决方案。一种解决方案是使用代码后台将DataContext强制转换为ViewModel类型并直接调用方法。例如:
// 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类型。这是我们想要避免的,因为它破坏了视图和ViewModel之间的关注点分离。
另一种方法是我自己使用的方法,当处理具有很少或没有数据绑定支持的自定义控件时。通过在视图上使用接口和附加属性,您可以将视图实例注入到ViewModel中并直接操作它。这是一种混合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");
}
}
如果需要包含注入器附加属性源代码的可下载演示,请参见此博客文章。同时还请参阅此前问题,两者相关联。
此致敬礼,