2012-05-22 69 views
1

我有一個文本框上的上下文菜單,我試圖通過值轉換器將isChecked屬性綁定到該文本框的datacontext中的某個屬性。找不到與參考綁定的元素'ElementName = Field'

我遇到的問題是非常相似的,我beleive,這個職位...... WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference

在有阿蘭穆赫蘭提出3個不同的解決方案。我一直努力工作的一個,還沒有看到實際的工作示例,就是#2。我認爲這是MVVM最友好的方法,併爲此最優雅......然後,我對此很新。

這是我的XAML

<DataTemplate x:Key="SFTemplateWithContextMenu"> 
     <TextBlock x:Name="Field" Text="{Binding Path=FieldName}" > 
     <TextBlock.ContextMenu> 
       <!--<ContextMenu PlacementTarget="{Binding ElementName=Field}" > --> 
        <ContextMenu DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=PlacementTarget.DataContext}"> 
        <MenuItem Header="Rename..." /> 
        <MenuItem Header="Field Type"> 
         <MenuItem.Resources> 
          <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" /> 
         </MenuItem.Resources> 
        <!--<MenuItem Header="String" IsCheckable="True" IsChecked="{Binding Path=PlacementTarget.DataContext.FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/>--> 
         <MenuItem Header="String" IsCheckable="True" IsChecked="{Binding Path=FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/> 
        </MenuItem> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </DataTemplate> 

我使用的DataTemplate來填充以下列表框...

<ListBox DnD:DragDropHelper.IsDragSource="True" Name="sourceFieldsLB" Height="238" HorizontalAlignment="Left" Margin="20,286,0,0" VerticalAlignment="Top" Width="150" ItemTemplate="{StaticResource SFTemplateWithContextMenu}" ItemsSource="{Binding Selection.SourceFields, Mode=TwoWay}" AllowDrop="True" > 

我下載史努比往裏看,看到剛剛是怎麼回事。我嘗試了幾種不同程度的失敗方法。

註釋掉的部分是以前我試圖完成我的目標的方法。問題是我得到的錯誤... 「找不到與參考綁定的源'elementname = Field'」但TextBlock使用Snoop顯示它的名稱是Field。

在目前我這樣做我可以看到textblock有一個本地名稱範圍,它的名稱是字段 - 這是我所期望和想要的。 ContextMenu值顯示它具有包含2個項目的ContextMenu ...這是正確的。所以我點擊ContextMenu來查看事物的外觀和低點,並注意到ContextMenu沒有DataContext。

任何幫助和方向,這將是偉大的。我不確定我在這裏錯過了什麼。我環顧四周,只要有人似乎接近完成這項工作,他們就會提到他們發現了一些「解決方法」或其他方式來做到這一點,並永遠無法實現。這必須有能力工作......我只是太新而不能看到缺失的部分。

我知道可以做一個真正的MVVM方式......對吧?

回答

1

Bryce,主要問題是ContextMenus不是標準可視化樹的一部分,它們唯一真正的連接是通過PlacementTarget屬性。所以,通常最好儘快把它勾起來。所以......

給出一個視圖模型

public class ViewModel 
{ 
    public string Field { get; set; } 
    public string FieldType { get; set; } 
} 

而且一個主窗口

<Window x:Class="ContextMenuSample.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <TextBlock Text="{Binding Field}"> 
      <TextBlock.ContextMenu> 
       <ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}"> 
        <MenuItem Header="{Binding FieldType}" /> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </Grid> 
</Window> 

而一個app.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Data; 
using System.Linq; 
using System.Windows; 

namespace ContextMenuSample 
{ 
    /// <summary> 
    /// Interaction logic for App.xaml 
    /// </summary> 
    public partial class App : Application 
    { 
     protected override void OnStartup(StartupEventArgs e) 
     { 
      base.OnStartup(e); 

      var shell = new MainWindow(); 
      shell.DataContext = new ViewModel { Field = "FirstName", FieldType = "String" }; 
      shell.Show(); 
     } 
    } 
} 

你可以看到,在DataContext爲ContextMenu通過線路正確連接

<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}"> 

你應該得到一個很好的表現的ContextMenu,它與底層的VieWModel對話。