c# - Caliburn.Micro:DataContext 上属性的调用方法

标签 c# wpf mvvm caliburn.micro

我有一个 MainView,它的 DataContext 是我的 MainViewModel。

主视图模型:

class MainViewModel : PropertyChangedBase
{
    #region Properties

    /// <summary>
    /// The ProjectViewModel.
    /// </summary>
    public ProjectViewModel ProjectVM
    {
        get { return _projectVM; }
        private set
        {
            _projectVM = value;
            NotifyOfPropertyChange(() => ProjectVM);
        }
    }
    private ProjectViewModel _projectVM;

    #endregion

    /// <summary>
    /// Constructor.
    /// </summary>
    public MainViewModel()
    {
        ProjectVM = new ProjectViewModel();
    }
}

现在,我的 MainView 上有一个菜单。我想将 MenItems 的 Click 事件绑定(bind)到 ProjectVM 对象上的方法。当然我知道我可以只设置 MenuItems 的 DataContext,但我想知道是否有更简单的方法。

目前我的 MainView 看起来像这样:
  <Grid>
<Grid.RowDefinitions>
  <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<Menu Grid.Row="0">
  <MenuItem Header="File">
    <MenuItem Header="New Project...">
      <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
          <cal:ActionMessage MethodName="ProjectVM.ShowNewProjectDialog"/>
        </i:EventTrigger>
      </i:Interaction.Triggers>
    </MenuItem>
    <MenuItem Header="Load Project..."/>
    <MenuItem Header="Close Project..."/>
  </MenuItem>
</Menu>

我曾希望 Caliburn 足够聪明地解决 ProjectVM.ShowNewProjectDialog,但事实并非如此。有什么好方法可以做到这一点而不必手动设置菜单的 DataContext 吗?

最佳答案

你是对的,Caliburn 并不那么聪明,无法解析 MethodName以您希望的方式拥有属性(property)。无论如何,它是一个强大的工具,可以根据您的需要轻松定制。

正如您在名为 All About Actions 的 Caliburn Micro 文档部分中所读到的那样:

ActionMessage is, of course, the Caliburn.Micro-specific part of this markup. It indicates that when the trigger occurs, we should send a message of “SayHello.” So, why do I use the language “send a message” instead of “execute a method” when describing this functionality? That’s the interesting and powerful part. ActionMessage bubbles through the Visual Tree searching for a target instance that can handle it.



这意味着 - 如果您需要 - 您可以手动设置将处理您的消息的“目标”。您可以使用 Action.Target附属属性(property)。当然你不想为每个 MenuItem 设置它。 ,所以你可以直接在你的Menu中设置目的:
<Menu cal:Action.Target="{Binding Path=ProjectVM, Mode=OneWay}">
    <MenuItem Header="File">
        <MenuItem Header="New Project..." cal:Message.Attach="ShowNewProjectDialog" />
        <MenuItem Header="Load Project..."/>
        <MenuItem Header="Close Project..."/>
    </MenuItem>
</Menu>

通过设置 Action.Target附加属性,我们声明来自菜单子(monad)级的所有消息(即 ActionMessages)将由 ProjectViewModel 处理。 .
现在,如果您运行您的项目,您会发现它不起作用。原因是 Caliburn Micro 使用 VisualTreeHelper用于遍历 XAML 树。为了我们的目的,我们需要使用 LogicalTreeHelper .

所以最后一步是在 Bootstrapper 中添加此代码Configure方法:
ActionMessage.SetMethodBinding = delegate(ActionExecutionContext context)
{
    FrameworkElement source = context.Source;
    for (DependencyObject dependencyObject = source; dependencyObject != null; dependencyObject = LogicalTreeHelper.GetParent(dependencyObject))
    {
        if (Caliburn.Micro.Action.HasTargetSet(dependencyObject))
        {
            object handler = Message.GetHandler(dependencyObject);
            if (handler == null)
            {
                context.View = dependencyObject;
                return;
            }
            MethodInfo methodInfo = ActionMessage.GetTargetMethod(context.Message, handler);
            if (methodInfo != null)
            {
                context.Method = methodInfo;
                context.Target = handler;
                context.View = dependencyObject;
                return;
            }
        }
    }
    if (source != null && source.DataContext != null)
    {
        object dataContext = source.DataContext;
        MethodInfo methodInfo2 = ActionMessage.GetTargetMethod(context.Message, dataContext);
        if (methodInfo2 != null)
        {
            context.Target = dataContext;
            context.Method = methodInfo2;
            context.View = source;
        }
    }
};

我希望它可以帮助你。

关于c# - Caliburn.Micro:DataContext 上属性的调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35151521/

相关文章:

c# - 风格完全改变

c# - 身份 View 在哪里?

c# - 处理MVVM下WPF中的 "X"关闭按钮

c# - 带有子集合的嵌套 ItemControls 上的 WPF 绑定(bind)

c# - 如何在 PHP 中复制此 C# 哈希? (toByteArray(), ComputeHash())

c# - 使用 Entity Framework 代码优先映射多个关系的问题

c# - 以编程方式更改 WPF 可编辑组合框的背景颜色

WPF 无模式对话框呈现文本框不可编辑

c# - WPF编译错误

c# - Caliburn 微 : passing Object between ViewModel