代码之家  ›  专栏  ›  技术社区  ›  iLemming

工具提示或上下文菜单中的相对资源绑定

  •  29
  • iLemming  · 技术社区  · 14 年前

     <GridViewColumn>
        <GridViewColumn.CellTemplate>
           <DataTemplate>
              <Button>
                <Button.ToolTip>
                  <TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" />
    

    这只是一个简单的例子,无论如何都行不通:) 实际上,我需要从窗口的DataContext范围内的另一个属性中获取一个值。

    4 回复  |  直到 14 年前
        1
  •  80
  •   Lynn Crumbling    9 年前

    这很棘手,因为工具提示不是VisualTree的一部分。 Here 您看到了一个很酷的解决方案,可以解决ContextMenus的相同问题。与工具提示的方式相同。

    更新
    遗憾的是,链接不见了,我再也找不到引用的文章了。

    一个很好的方法是在PlacementTarget的Tag属性中提供所需的实例(例如ViewModel)。以下示例用于访问ViewModel的命令实例:

    <Button Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=Self}}">
      <Button.ContextMenu>
        <ContextMenu>
           <MenuItem Command="{Binding PlacementTarget.Tag.DesiredCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" .../>
        <ContextMenu>
      </Button.ContextMenu>
    </Button>
    

    我没有测试过它,上一次我做了很长时间了。如果不适合你,请发表评论。

    更新2

    因为这个答案的原始链接已经不存在了,我点击了存档.org和 found the original blog entry . 以下是博客中的逐字记录:

    因为WPF中的ContextMenu在的可视化树中不存在 我在网上到处寻找这个,而且 常见的答案似乎是只在代码后面做。错了!我 在代码后面做事情。

    作为窗口的属性存在。

    public partial class Window1 : Window
    {
        public Window1()
        {
            MyString = "Here is my string";
        }
    
        public string MyString
        {
            get;
            set;
    
        }
    }
    
    
    <Button Content="Test Button" 
         Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
      <Button.ContextMenu>
        <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, 
              RelativeSource={RelativeSource Self}}" >
          <MenuItem Header="{Binding MyString}"/>
        </ContextMenu>
      </Button.ContextMenu>   
    </Button>
    

    重要的部分是按钮上的标签(尽管您可以 轻松设置按钮的DataContext)。它存储对的引用 父窗口。ContextMenu可以访问 通过PlacementTarget属性。然后可以传递此上下文 在你的菜单上。

    然而,它比在代码后面设置东西要好。如果有人

        2
  •  5
  •   rr789    7 年前

    根据以下内容:
    PlacementTarget是拥有ContextMenu的控件(例如:DataGrid)。不需要“标签”属性。

    IsEnabled绑定到DataGrid的“myProperty”值。

    <ContextMenu
    DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"
    IsEnabled="{Binding myProperty}"  
    >
    
        3
  •  -1
  •   Amir Oveisi    8 年前

    因为 ContextMenu 不在可视树中,绑定将不起作用。 一个简单的解决方案是使用代理模式,您可以创建一个从 DependencyObject 而且有一个 DependencyProperty 这将保持 DataContext 你的 Window ,则可以在XAML中拥有代理的资源,并最终绑定 MenuItem 通过代理对象将命令转换为所需的命令。

    Public class ProxyClass : DependencyObject
    {
        Public object Data {get; set;}
       public static readonly DependencyProperty DataProperty = DependencyProperty.Register("DataProperty", typeof(object), typeof(ProxyClass), new FrameworkPropertyMetadata(null));
    
    }
    

    <Window DataContext="{Binding MyViewModel}">
    ...
    <Window.Resources>
        <ProxyClass Data={Binding} x:Key="BindingProxy"/>
    
    </Window.Resources>
    ...  
    <MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/>
    ...
    </Window>
    

    发生了什么事?
    Data 财产 ProxyClass 属于 窗口 ,那么它就拥有了你的全部财产 ViewModel 内部
    这种方法的另一个好处是可移植性和在多个视图和项目中重用。

        4
  •  -3
  •   mdm20    14 年前

    我认为应该这样做:

    {Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"