Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将MenuItem命令关联到视图上的自定义命令和方法_C#_Wpf_Events_Command - Fatal编程技术网

C# 如何将MenuItem命令关联到视图上的自定义命令和方法

C# 如何将MenuItem命令关联到视图上的自定义命令和方法,c#,wpf,events,command,C#,Wpf,Events,Command,我在视图上有一个简单的文本块,为其添加了一个上下文菜单。我想连接命令,让MenuItem在视图上执行一个方法。在一天的大部分时间里,我只找到了一个有效的解决方案,这让我相信我错过了什么。有太多的事情对我来说毫无意义 这是我唯一能让它工作的方法 <TextBlock Text="Test"> <TextBlock.ContextMenu> <ContextMenu> <MenuItem Header="Tes

我在视图上有一个简单的文本块,为其添加了一个上下文菜单。我想连接命令,让MenuItem在视图上执行一个方法。在一天的大部分时间里,我只找到了一个有效的解决方案,这让我相信我错过了什么。有太多的事情对我来说毫无意义

这是我唯一能让它工作的方法

<TextBlock Text="Test">
    <TextBlock.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Test Me" Command="w:Command.TestMe" />
        </ContextMenu>
    </TextBlock.ContextMenu>
</TextBlock>

public static class Command
{
    public static readonly RoutedUICommand TestMe= new RoutedUICommand("Test Me", "TestMe", typeof(MainWindow));
}
为什么当我在XAML中声明CommandBindings时,我终于让它工作了,但MenuItem总是被禁用

<Window.CommandBindings>
    <CommandBinding Command="w:Command.TestMe" Executed="TestMeDetails" CanExecute="CanTestMe" /> 
</Window.CommandBindings> 

为什么RouteDuicCommand类必须是单独静态类中的一个类才能工作,但它有一个typeof(MainWindow)而不是自身的静态实例typeof(Command)?一定有一点我不明白。当然,将一个简单的命令事件连接到按钮或元素不会如此复杂?

理想情况下,
ICommand
应该留在ViewModel中,但如果您想在窗口的代码隐藏中创建它,您也可以实现它(无需创建RoutedCommand)

<>你可以像你在ViewModel那样绑定命令,但是在那之前你需要考虑这些情况。
  • 上下文菜单不在应用它的控件的同一个可视树中。所以,要绑定父窗口,必须使用
    PlacementTarget
  • 一旦获得放置目标,就可以像对待ViewModel中的任何命令一样使用代码隐藏进行绑定
  • 此代码将在以下情况下工作:

    XAML

    <TextBlock Text="Test"
                Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                                         AncestorType=Window}}">
        <TextBlock.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Test Me"
                          Command="{Binding PlacementTarget.Tag.TestCommand, 
                                   RelativeSource={RelativeSource Mode=FindAncestor, 
                                                      AncestorType=ContextMenu}}"/>
            </ContextMenu>
        </TextBlock.ContextMenu>
    </TextBlock>
    

    我看到了标题的编辑。我应该在标题中省略特定于语言的标识符吗?如果是这样的话,我会确保从现在开始。谢谢是的,标签就是为了这个目的。还有,如果这能解决你的问题,有什么理由不接受这个答案吗?请原谅我的态度,接受我的道歉。我之前以为我已经接受了答案并添加了一个感谢,但我可能已经将它添加到了另一个线程中。你的回答是正确的,极大地帮助我走上正轨!我非常感谢你的回答和背后的解释。非常感谢。
    public ICommand TestCommand
        {
            get
            {
                if (testCommand == null)
                    testCommand = new RelayCommand(param => TestMeDetails(), param => CanTestMe());
    
                return changeStatusCommand;
            }
        } 
    
    public bool CanTestMe()
    {
        return true;
    }
    
    public void TestMeDetails() { }
    
    <TextBlock Text="Test"
                Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                                         AncestorType=Window}}">
        <TextBlock.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Test Me"
                          Command="{Binding PlacementTarget.Tag.TestCommand, 
                                   RelativeSource={RelativeSource Mode=FindAncestor, 
                                                      AncestorType=ContextMenu}}"/>
            </ContextMenu>
        </TextBlock.ContextMenu>
    </TextBlock>
    
    private ICommand testCommand;
    public ICommand TestCommand
    {
        get
        {
            if (testCommand == null)
                testCommand = new RelayCommand(param => TestMeDetails(),
                                               param => CanTestMe());
    
            return testCommand;
        }
    }
    
    public bool CanTestMe()
    {
        return true;
    }
    
    public void TestMeDetails() { }