C# 无法将可检查菜单项绑定到父窗口';s最顶层(始终位于顶部)属性

C# 无法将可检查菜单项绑定到父窗口';s最顶层(始终位于顶部)属性,c#,wpf,data-binding,relativesource,findancestor,C#,Wpf,Data Binding,Relativesource,Findancestor,我不知道我哪里出了问题。希望你们中有人能帮忙 我有一个包含TabControl的窗口。TabControl有一个ContextMenu,其中有一个“始终在顶部”行为的可检查项。我想将此可检查项绑定到包含窗口的布尔最顶层属性 无论我做什么,绑定都会失败,并且在调试输出中出现“找不到绑定源”错误 (这些摘录大大简化了我的实际代码。我希望我没有意外删掉任何相关内容。) 首先我尝试了这个: <Window x:Name="myWindow" (blah blah other properties)

我不知道我哪里出了问题。希望你们中有人能帮忙

我有一个包含TabControl的窗口。TabControl有一个ContextMenu,其中有一个“始终在顶部”行为的可检查项。我想将此可检查项绑定到包含窗口的布尔最顶层属性

无论我做什么,绑定都会失败,并且在调试输出中出现“找不到绑定源”错误

(这些摘录大大简化了我的实际代码。我希望我没有意外删掉任何相关内容。)

首先我尝试了这个:

<Window x:Name="myWindow" (blah blah other properties)>
    <TabControl x:Name="tabControl">
        <TabControl.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Always on Top" IsCheckable="True"
                          IsChecked="{Binding ElementName=myWindow,
                                              Path=Topmost,
                                              Mode=TwoWay}"/>
            </ContextMenu>
        ...
<Window x:Name="myWindow" (blah blah other properties)>
    <TabControl x:Name="tabControl">
        <TabControl.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Always on Top" IsCheckable="True"
                          IsChecked="{Binding RelativeSource={
                                                  RelativeSource FindAncestor,
                                                  AncestorType={x:Type Window}
                                              },
                                              Path=Topmost,
                                              Mode=TwoWay}"/>
            </ContextMenu>
        ...

...
那没用。是因为菜单项在“myWindow”窗口的内部吗?我需要使用RelativeSource祖先绑定吗

所以我尝试了这个:

<Window x:Name="myWindow" (blah blah other properties)>
    <TabControl x:Name="tabControl">
        <TabControl.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Always on Top" IsCheckable="True"
                          IsChecked="{Binding ElementName=myWindow,
                                              Path=Topmost,
                                              Mode=TwoWay}"/>
            </ContextMenu>
        ...
<Window x:Name="myWindow" (blah blah other properties)>
    <TabControl x:Name="tabControl">
        <TabControl.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Always on Top" IsCheckable="True"
                          IsChecked="{Binding RelativeSource={
                                                  RelativeSource FindAncestor,
                                                  AncestorType={x:Type Window}
                                              },
                                              Path=Topmost,
                                              Mode=TwoWay}"/>
            </ContextMenu>
        ...

...
那也没用

所以现在我被卡住了。我如何使这个装订工作


注意:我的代码隐藏没有对这些元素执行任何操作。我需要设置Window.DataContext还是什么?这可能会破坏此窗口的其他部分。

据我所知,菜单是在弹出窗口中绘制的,而该弹出窗口实际上不是窗口视觉树的一部分。因此,最好尝试在此处使用MVVM,并通过视图模型设置IsChecked。

是的,无论“最顶端”属性所在的对象是什么,都必须设置为窗口的DataContext。如果将其设置为窗口的DataContext,则控件应该能够从您在第一个示例中尝试的ElementName绑定中拾取属性


您的视图将查看其DataContext中名为“TopMost”的属性

,该属性将解释FindAncestor可能不起作用的原因,但不会解释ElementName不起作用的原因。DataContext和ElementName之间的关系是什么?看起来它们都做了相同的事情,不是吗?DataContext是表示视图的支持属性的对象。任何简单的绑定表达式都会在其DataContext上查找绑定到的属性。ElementName绑定意味着将一个元素的属性绑定到另一个元素的属性(就像将文本框的文本属性绑定到按钮的内容属性)。我仍然不明白。我正在“将一个元素的属性绑定到另一个元素的属性”(也就是说,我正在将MenuItem.IsChecked绑定到myWindow.topmest)。DataContext有什么用途?为什么除了我给它的显式元素名之外,它还会在其他地方出现呢?好的,考虑一下最上面的属性与窗口的关系。如果未设置窗口的DataContext,则它与最顶层的属性没有关系。相信我,如果你实例化了一个包含最顶层属性的对象,然后将窗口的DataContext设置为该对象,那么你的ElementName绑定就会工作,因为这样你就创建了最顶层属性和窗口视图之间的关系。我从绑定中完全删除了ElementName,并在codebehind中设置DataContext=this。。。成功了!我猜您想说的是,所有绑定都是相对于DataContext的(除非您执行RelativeSource或其他操作)。是这样吗?