Caliburn Micro 的动态菜单和子菜单,如何绑定命令?
Dynamic menus and submenus with Caliburn Micro, how can I bind the commands?
我在 WPF 项目中使用 Caliburn Micro,我希望插件组件能够填充工具栏。每个插件都有一个顶级菜单项,如果他们愿意,可以用子菜单填充它。
<ToolBar>
<Menu x:Name="ToolBarMenuItems">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=Text}" />
<Setter Property="ItemsSource" Value="{Binding Path=Children}" />
</Style>
</Menu.ItemContainerStyle>
</Menu>
</ToolBar>
ToolBarMenuItems 是接口的 BindableCollection:
public BindableCollection<IMenuItemViewModel> ToolBarMenuItems { get; set; }
public interface IMenuItemViewModel
{
string Text { get; set; }
ObservableCollection<IMenuItemViewModel> Children { get; set; }
bool CanRunCommand();
void RunCommand();
}
就创建菜单而言,这工作正常,问题是将菜单项连接到 RunCommand/CanRunCommand。 Dynamic menus with Caliburn micro 解释了如何在 MenuItem 上执行此操作:
<Menu>
<MenuItem x:Name="ToolBarMenuItems" DisplayMemberPath="Text" Header="MyMenu" cal:Message.Attach="RunToolbarCommand($originalsourcecontext)"/>
</Menu>
其中RunToolBarCommand是view model中的一个方法public void RunToolbarCommand(IMenuItemViewModel menuItem)
而$originalsourcecontext是指在bootstrapper中设置如下
MessageBinder.SpecialValues.Add("$originalsourcecontext", context =>
{
var args = context.EventArgs as RoutedEventArgs;
var fe = args?.OriginalSource as FrameworkElement;
return fe?.DataContext;
});
但正如我所说,我需要对整个菜单执行此操作,而不仅仅是在 MenuItem 上执行此操作,但我不知道如何使用 Caliburn Micro 来绑定方法。
将 setter 添加到您的 Style
以设置 cal:Message.Attach
附加 属性 并传递 $executionContext
:
<Menu x:Name="ToolBarMenuItems">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=Text}" />
<Setter Property="ItemsSource" Value="{Binding Path=Children}" />
<Setter Property="cal:Message.Attach" Value="RunCommand($executionContext)" />
</Style>
</Menu.ItemContainerStyle>
</Menu>
您需要接口和实现中的上下文才能阻止事件冒泡:
public void RunCommand(ActionExecutionContext context)
{
if (context?.EventArgs is RoutedEventArgs routedEventArgs)
routedEventArgs.Handled = true;
MessageBox.Show("Run!");
}
请参阅 问题了解更多信息。
我在 WPF 项目中使用 Caliburn Micro,我希望插件组件能够填充工具栏。每个插件都有一个顶级菜单项,如果他们愿意,可以用子菜单填充它。
<ToolBar>
<Menu x:Name="ToolBarMenuItems">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=Text}" />
<Setter Property="ItemsSource" Value="{Binding Path=Children}" />
</Style>
</Menu.ItemContainerStyle>
</Menu>
</ToolBar>
ToolBarMenuItems 是接口的 BindableCollection:
public BindableCollection<IMenuItemViewModel> ToolBarMenuItems { get; set; }
public interface IMenuItemViewModel
{
string Text { get; set; }
ObservableCollection<IMenuItemViewModel> Children { get; set; }
bool CanRunCommand();
void RunCommand();
}
就创建菜单而言,这工作正常,问题是将菜单项连接到 RunCommand/CanRunCommand。 Dynamic menus with Caliburn micro 解释了如何在 MenuItem 上执行此操作:
<Menu>
<MenuItem x:Name="ToolBarMenuItems" DisplayMemberPath="Text" Header="MyMenu" cal:Message.Attach="RunToolbarCommand($originalsourcecontext)"/>
</Menu>
其中RunToolBarCommand是view model中的一个方法public void RunToolbarCommand(IMenuItemViewModel menuItem)
而$originalsourcecontext是指在bootstrapper中设置如下
MessageBinder.SpecialValues.Add("$originalsourcecontext", context =>
{
var args = context.EventArgs as RoutedEventArgs;
var fe = args?.OriginalSource as FrameworkElement;
return fe?.DataContext;
});
但正如我所说,我需要对整个菜单执行此操作,而不仅仅是在 MenuItem 上执行此操作,但我不知道如何使用 Caliburn Micro 来绑定方法。
将 setter 添加到您的 Style
以设置 cal:Message.Attach
附加 属性 并传递 $executionContext
:
<Menu x:Name="ToolBarMenuItems">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=Text}" />
<Setter Property="ItemsSource" Value="{Binding Path=Children}" />
<Setter Property="cal:Message.Attach" Value="RunCommand($executionContext)" />
</Style>
</Menu.ItemContainerStyle>
</Menu>
您需要接口和实现中的上下文才能阻止事件冒泡:
public void RunCommand(ActionExecutionContext context)
{
if (context?.EventArgs is RoutedEventArgs routedEventArgs)
routedEventArgs.Handled = true;
MessageBox.Show("Run!");
}
请参阅