2012-11-15 64 views
1

我有一個TreeView我正在填充並添加一個ContextMenu到每個項目。問題出在我的ViewModel中,TreeView的ItemSource綁定到ViewModel本身的一個屬性上。當我試圖再次引用ViewModel上的某些屬性時,我似乎無法使其工作。WPF中的父對象DataBinding

<TreeView Grid.ColumnSpan="1" Grid.Row="1" HorizontalAlignment="Stretch" ItemsSource="{Binding ModelItems}" SelectedTreeItem="{Binding SelectedItem, Mode=TwoWay}" VerticalAlignment="Stretch" Grid.RowSpan="3" Margin="5"> 
<TreeView.ItemTemplate> 
    <HierarchicalDataTemplate ItemsSource="{Binding Models}"> 
     <TextBlock Text="{Binding Header, Mode=TwoWay}" ToolTip="{Binding Tooltip, Mode=TwoWay}"> 
      <TextBlock.ContextMenu> 
       <ContextMenu> 
        <MenuItem Header="Server" Visibility="{Binding Path=IsServerVisible}"> 
         <MenuItem Header="Add" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Windows:MainWindow}}, Path=ViewModel:ViewModel.AddServerCommand}"/> 
         <MenuItem Header="Edit" /> 
         <MenuItem Header="Delete" /> 
        </MenuItem> 
        <MenuItem Header="Config" Visibility="{Binding Path=IsConfigVisible}"> 
         <MenuItem Header="Fetch" /> 
         <MenuItem Header="Edit" /> 
         <MenuItem Header="Save" /> 
        </MenuItem>  
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </HierarchicalDataTemplate>     
</TreeView.ItemTemplate> 

一前一後在計算器上指出我在使用的RelativeSource正確綁定到我的主窗口視圖模型的方向。但是,當我運行該應用程序時,該命令不起作用,並且輸出窗口不會生成任何可以看到的綁定或xaml錯誤。

基本上可見性綁定工作,因爲這些屬性存在於「模型」項目。不過,我希望一切都被移到ViewModel,特別是命令。

任何人都可以發現我在這裏做錯了嗎?

+0

其實我能夠得到錯誤消息輸出: System.Windows.Data錯誤:4:無法找到綁定的源參考'RelativeSource FindAncestor,AncestorType ='Windows.MainWindow',AncestorLevel ='1'' 。 BindingExpression:路徑=視圖模型:ViewModel.AddServerCommand;的DataItem = NULL;目標元素是'MenuItem'(Name ='');目標屬性是'命令'(類型'ICommand') – Tada

回答

3

這裏要記住的關鍵是上下文菜單不是視覺樹的一部分。

因此,它們不會繼承與它們屬於綁定的控件相同的源。處理這個問題的方法是綁定到ContextMenu本身的placement target。但既然你要綁定它的命令在ViewModel類,請將您的TextBlock和使用DataContext in Tag在命令綁定這樣的 -

<HierarchicalDataTemplate ItemsSource="{Binding Models}"> 
    <TextBlock Text="{Binding Header}" 
       Tag="{Binding DataContext, RelativeSource= 
       {RelativeSource Mode=FindAncestor, AncestorType=Window}}"> 
     <TextBlock.ContextMenu> 
       <ContextMenu> 
        <MenuItem Header="Server" Command="{Binding 
          PlacementTarget.Tag.AddServerCommand, 
          RelativeSource={RelativeSource Mode=FindAncestor, 
          AncestorType=ContextMenu}}"/> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
</HierarchicalDataTemplate> 

使用其他綁定類似像上面,它會工作,你想怎麼。

+0

我覺得我有一半明白爲什麼這個工作,一半我不知道。我接受了這個答案,因爲這是我嘗試過的第一個作品。所以我猜TextBlock上的標籤創建了一個對我的DataContext的引用,然後MenuItem使用它和相關的源來查找標籤引用。非常整潔謝謝你。 – Tada

+0

是的,你說得對。標籤持有對您的DataContext的引用。 –

+1

再次感謝,我想今天我會再次頭痛! – Tada

0

因爲您沒有發佈完整的.xaml,所以讓我們使用treeview的datacontext。因爲RelativeSource允許我們訪問TreeView,所以需要在綁定路徑中使用DataContext,因爲這是對ViewModel的引用。

Command="{Binding Path="DataContext.AddServerCommand" RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeView}}}" 
+0

所以我試過這個以及它仍然不能解析爲有效的參考。我知道我正在使用正確的語法和所有。奇怪的事情正在發生。 – Tada

+0

http://stackoverflow.com/questions/1013558/elementname-binding-from-menuitem-in-contextmenu這些解決方案應該工作。如果它有效的話,我會親自去找4個upvotes的.xaml綁定。 –

0

而不是

<MenuItem Header="Add" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Windows:MainWindow}}, Path=ViewModel:ViewModel.AddServerCommand}"/> 

嘗試

<MenuItem Header="Add" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Windows:MainWindow}}, Path=DataContext.AddServerCommand}"/> 

是不是你的ViewModel你的DataContext?