【问题标题】:Cannot find sourcefor binding with reference 'ElementName=Field'找不到与引用'ElementName = Field'的绑定的源
【发布时间】:2012-05-22 21:10:16
【问题描述】:

我在文本框上有一个上下文菜单,我正在尝试使用值转换器将 isChecked 属性绑定到该文本框的 datacontext 中的属性之一。

我相信,我遇到的问题与这篇文章非常相似...WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference

在那里,Aran Mulholland 提出了 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...

<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" >

我下载了 Snoop 以查看内部情况,看看发生了什么。我尝试了几种不同的方法,但都失败了。

注释掉的部分是我之前尝试实现目标的方式。问题是我得到了错误...... “找不到与引用'elementname = Field'绑定的源”但是TextBlock使用Snoop显示它的名字是字段。

以我目前的方式,我可以看到文本块有一个本地名称范围,它的名称是 Field - 这是我所期望和想要的。 ContextMenu 值表明它有一个带有 2 个项目的 ContextMenu ......这是正确的。所以我点击了 ContextMenu 看看事情的外观和低级,发现 ContextMenu 没有 DataContext。

对此的任何帮助和指导都会非常有用。我不确定我在这里缺少什么。我环顾四周,每当有人似乎接近完成这项工作时,他们都会提到他们找到了一些“解决方法”或其他方法来做到这一点,但永远不会让它发挥作用。这必须有能力工作......我对此太陌生了,看不到缺失的部分。

我知道可以做一个真正的 MVVM 方式......对吗?

【问题讨论】:

    标签: wpf binding mvvm contextmenu datacontext


    【解决方案1】:

    Bryce,主要问题是 ContextMenus 不是标准可视化树的一部分,它们唯一真正的联系是通过 PlacementTarget 属性。因此,通常最好尽快将其连接起来。所以……

    给定一个 ViewModel

    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();
            }
        }
    }
    

    您可以看到 ContextMenu 的 DataContext 已通过该行正确连接

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

    你应该得到一个与底层 VieWModel 对话的行为良好的 ContextMenu。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 2018-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多