2010-09-08 59 views
25

結合我在做什麼錯在這裏?:的RelativeSource從工具提示或文本菜單

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

這只是一個簡單的例子,不反正工作:) 其實我需要從另一個屬性得到一個值即在Window的DataContext範圍內。

幫我看看。

回答

63

這很棘手,因爲ToolTip不是VisualTree的一部分。 Here你看到了與ContextMenus相同的問題的一個很酷的解決方案。您可以使用工具提示的相同方式。

UPDATE
可悲的是鏈接不見了,我還沒有發現引用的文章了。
據我所知,被引用的博客展示瞭如何綁定到另一個VisualTree的DataContext,這通常是從ToolTip,ContextMenu或Popup綁定時必需的。

一個很好的方法是在PlacementTarget的Tag屬性中提供所需的實例(例如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

由於原來的鏈接,這個答案是寫走了,我打archive.org和found the original blog entry。這是逐字從博客:

因爲一個文本菜單中的WPF不 你的頁面/窗口/控件本身的可視化樹中存在,數據綁定可以是一個有點棘手。 我在網上爲此搜索了高低,最常見的答案似乎是「只是在後面的代碼中做」。錯誤!我並沒有進入到XAML的美妙世界,因爲它會在代碼背後回到 處事。

這裏是我的例子,它允許你將一個字符串綁定到 作爲窗口的一個屬性。

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屬性訪問此 。然後您可以通過您的菜單項向下傳遞這個上下文 。

我承認這不是世界上最優雅的解決方案。 但是,它在代碼背後跳動設置的東西。如果任何人有更好的方式來做到這一點,我很樂意聽到它。

+0

這就是它!謝謝! – Agzam 2010-09-08 14:36:34

+0

該鏈接已死亡。你能填寫缺失的信息嗎? – 2012-08-08 17:36:25

+1

@Bill我還沒有找到鏈接,但我試圖解釋如何解決問題的方式。 – HCL 2012-08-08 18:32:08

-2

我覺得應該這樣做:

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

不...不起作用。我已經試過那個... – Agzam 2010-09-08 14:26:15

+0

這不是因爲VisualTree的主要工具提示不可用。看到我的答案。 – HCL 2010-09-08 14:31:30

+0

對不起,實際上並沒有注意到它在工具提示中。 – mdm20 2010-09-08 15:12:49

0

因爲ContextMenu是不是在視覺樹,結合將無法正常工作。 一個簡單的解決方案是使用代理模式,您可以創建一個包裝類繼承DependencyObjectDependencyProperty,將保留WindowDataContext,然後您可以在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)); 

} 

如何在XAML中使用:

<Window DataContext="{Binding MyViewModel}"> 
... 
<Window.Resources> 
    <ProxyClass Data={Binding} x:Key="BindingProxy"/> 

</Window.Resources> 
... 
<MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/> 
... 
</Window> 

這是怎麼回事?的ProxyClass
Data屬性將綁定到的WindowDataContext,那麼它所有的comamnds和ProxyClass資源裏面你ViewModel的屬性。
這種方法的另一個好處是在多個視圖和項目中的可移植性和重用性。

2

以下爲:
PlacementTarget是擁有ContextMenu(例如:DataGrid)的控件。不需要「標籤」屬性。

IsEnabled綁定到DataGrid的「myProperty」值。

我測試了這個,它的工作原理。與綁定有類似的問題。

<ContextMenu 
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}" 
IsEnabled="{Binding myProperty}" 
> 
相關問題