我有一个带有" MainView"的Catel应用程序。和一些嵌套的视图。
嵌套视图的ListView
包含一些ContextMenu
项MenuItems
的项目。
在MainView的ViewModel中,我创建了一个TaskCommand<object>
,它将对传递的参数执行某些操作。此传递的参数应该是SelectedItem
的当前ListView
。此命令正在全球注册到ICommandManager
。
如果我使用MenuItem
中带有绑定命令的ICommandManager
点击,则传递的参数将始终为null
。
这里有相关代码:
NestedView.xaml :
<catel:UserControl
x:Name="UserControl"
x:Class="My.NameSpace.Views.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:catel="http://catel.codeplex.com">
...
<ListView ItemsSource="{Binding Items}"
BorderThickness="0"
SelectedItem="{Binding SelectedItem}"
HorizontalContentAlignment="Stretch">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Margin="2.5"
Text="{Binding Description}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Do Stuff"
Command="{catel:CommandManagerBinding DoStuffCommand}"
CommandParameter="{Binding DataContext.SelectedItem, ElementName=UserControl}" />
...
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
...
</catel:UserControl>
MainViewModel.cs :
public class MainViewModel : ViewModelBase {
...
public ICommand DoStuffCommand { get; }
public MainViewModel(ICommandManager commandManager, IUIVisualizerService uiVisualizerService, IMessageService messageService)
{
...
DoStuffCommand = new TaskCommand<object>(OnDoStuffCommandExecute);
commandManager.CreateCommand(nameof(DoStuffCommand));
commandManager.RegisterCommand(nameof(DoStuffCommand), DoStuffCommand, this);
}
private async Task OnDoStuffCommandExecute(object parameter)
{
// command needs to be in the MainViewModel because there will be some modification on the MainView based on parameter (adding tabs, etc)
Debugger.Break();
}
...
}
如果您需要更多代码,我也可以发布此代码,但这应该足够了。
我还看了一下Catel的CommandManager
实现,发现了这个:
/// <summary>
/// Executes the command.
/// </summary>
/// <param name="commandName">Name of the command.</param>
/// <exception cref="ArgumentException">The <paramref name="commandName"/> is <c>null</c> or whitespace.</exception>
/// <exception cref="InvalidOperationException">The specified command is not created using the <see cref="CreateCommand"/> method.</exception>
public void ExecuteCommand(string commandName)
{
Argument.IsNotNullOrWhitespace("commandName", commandName);
lock (_lockObject)
{
Log.Debug("Executing command '{0}'", commandName);
if (!_commands.ContainsKey(commandName))
{
throw Log.ErrorAndCreateException<InvalidOperationException>("Command '{0}' is not yet created using the CreateCommand method", commandName);
}
_commands[commandName].Execute(null);
}
}
我假设如果单击MenuItem
将会调用此方法并解释行为。
是否有适当的解决方案/解决方法将(绑定)参数传递给我的OnExecute
方法?
提前致谢
答案 0 :(得分:1)
在xaml中命令绑定之前设置CommandParameter
绑定
MenuItem Header =“Do Stuff” CommandParameter =“{Binding DataContext.SelectedItem,ElementName = UserControl}” Command =“{catel:CommandManagerBinding DoStuffCommand}”
请注意,菜单项中的绑定上下文是项,而不是视图模型。如果要绑定到视图模型,则需要为根网格提供一个名称,并按以下方式绑定:
CommandParameter="{Binding DataContext.SelectedItem, ElementName=rootGrid}"
请注意,使用UserControl
无法正常工作,因为VM已设置在内部网格中(有关解释原因,请参阅文档)。因此,请使用UserControl.ViewModel
或SomeInnerControl.DataContext
答案 1 :(得分:1)
好的,我找到了解决方案,但实际上有点奇怪。
首先交换Command={...}
和CommandParamter={...}
的顺序(如Geert所说)。
然后经过很多失败后我才开始工作:只需进入CommandParameter
- 绑定标记而不是其他任何东西。所以MenuItem
的我的XAML代码如下所示:
<MenuItem Header="Do Stuff"
CommandParameter="{Binding}"
Command="{catel:CommandManagerBinding DoStuffCommand}"/>
好的,现在我得到了一个解决方案(我认为)。上面的方法大部分时间都有效,但可能会遇到问题,因为@ mm8指出。
所以我用Google搜索了更多内容并发现:https://stackoverflow.com/a/3668699(请参阅更新2)
在这个给出的答案解决方案现在对我来说很好,因为我可以直接绑定到我的ViewModel
并通过绑定获得所需的值。