在Caliburn.Micro中如何将动作绑定到嵌套的ViewModel方法?

我有一个WPF应用程序,由Caliburn.Micro提供支持,是视图模型的第一种方法。 有一个命令栏类型的控件,其CommandBarView.xaml和绑定的CommandBarViewModel 。 命令栏VM包含许多嵌套的VM,每个按钮控件一个,所有这些都显示一个公共接口并具有共同的行为。 命令栏VM公开它们以便可以从视图绑定它们:

public interface IWarningButtonViewModel { bool IsVisible { get; } bool CanShowWarning { get; } void ShowWarning(); } public class CommandBarViewModel : PropertyChangedBase { public IWarningButtonViewModel UserNotFoundWarning { get; private set; } public IWarningButtonViewModel NetworkProblemWarning { get; private set; } // ... initialization omitted for simplicity } 

对于一些CommandBarView,这是一个暂定的XAML:

  

通过这种方式,我能够成功绑定两个属性( CanShowWarningIsVisible ),但我无法将按钮命令/动作绑定到ShowWarning方法。

我试过深度属性绑定 ,它再次适用于属性,但不适用于操作。
我还尝试了混合使用cal:Model.Bindcal:Message.Attach

  

这似乎在运行时工作,但cal:Model.Bind使VS设计器完全无法使用,UI控件不显示。

我搜索了很多,但我找不到一个让我也能与设计师合作的实际解决方案。 我觉得很奇怪,我只能找到属性的深层绑定示例,而不是动作。

知道怎么解决这个问题吗?

这是我的解决方法:

 private static void EnableNestedViewModelActionBinding() { var baseGetTargetMethod = ActionMessage.GetTargetMethod; ActionMessage.GetTargetMethod = (message, target) => { var methodName = GetRealMethodName(message.MethodName, ref target); if (methodName == null) return null; var fakeMessage = new ActionMessage { MethodName = methodName }; foreach (var p in message.Parameters) fakeMessage.Parameters.Add(p); return baseGetTargetMethod(fakeMessage, target); }; var baseSetMethodBinding = ActionMessage.SetMethodBinding; ActionMessage.SetMethodBinding = context => { baseSetMethodBinding(context); var target = context.Target; if (target != null) { GetRealMethodName(context.Message.MethodName, ref target); context.Target = target; } }; } private static string GetRealMethodName(string methodName, ref object target) { var parts = methodName.Split('.'); var model = target; foreach (var propName in parts.Take(parts.Length - 1)) { if (model == null) return null; var prop = model.GetType().GetPropertyCaseInsensitive(propName); if (prop == null || !prop.CanRead) return null; model = prop.GetValue(model); } target = model; return parts.Last(); } 

从引导程序中调用EnableNestedViewModelActionBinding()一次,它将允许您使用通常的点分表示法将操作绑定到嵌套模型的方法。 例如

 cal:Message.Attach="[Event Click] = [Action UserNotFoundWarning.ShowWarning]" 

编辑:请注意,如果您在运行时更改嵌套的ViewModel实例,这将不起作用。 例如,如果在绑定发生后将UserNotFoundWarning分配给新的东西 – Caliburn仍然会在之前的实例上调用操作。