这份原稿.如何将操作绑定到嵌套的ViewModel方法
本文关键字:绑定 嵌套 方法 ViewModel 操作 | 更新日期: 2023-09-27 18:07:58
我有一个WPF应用程序,由Caliburn提供支持。微观的,视图模型优先的方法。有一个命令栏类型的控件,它的CommandBarView。xaml和bound CommandBarViewModel。命令栏虚拟机拥有许多嵌套的虚拟机,每个按钮控件一个,所有显示一个共同的界面和具有共同的行为。命令栏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
}
这是一个试探性的XAML的一点CommandBarView:
<Button x:Name="UserNotFoundWarning_ShowWarning"
IsEnabled="{Binding UserNotFoundWarning.CanShowWarning}">
...
<DataTrigger Binding="{Binding UserNotFoundWarning.IsVisible}" Value="True">
...
</Button>
通过这种方式,我能够成功地绑定两个属性(CanShowWarning, IsVisible),但是我不能将按钮命令/动作绑定到ShowWarning方法。
我尝试了深度属性绑定,它再次适用于属性,但不适用于动作。
我还尝试了cal:Model.Bind
和cal:Message.Attach
的混合:
<Button cal:Model.Bind="{Binding UserNotFoundWarning}"
cal:Message.Attach="[Event Click] = [Action ShowWarning]"
IsEnabled="{Binding CanShowWarning}">
...
<DataTrigger Binding="{Binding IsVisible}" Value="True">
...
</Button>
这似乎在运行时工作,但调用: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]"
Edit:请注意,如果您在运行时更改嵌套的ViewModel实例,这将不起作用。例如,如果你在绑定发生后将UserNotFoundWarning
分配给新的东西- Caliburn仍然会调用先前实例的操作。