2012-05-22 2 views
1

isChecked 속성을 값 변환기가있는 해당 텍스트 상자의 datacontext에있는 속성 중 하나에 바인딩하려고하는 텍스트 상자에 컨텍스트 메뉴가 있습니다. 'ElementName = Field'참조로 소스 바인딩을 찾을 수 없습니다.

나는 데 문제

가 아란 멀홀랜드에서

WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference은 3 개 가지 솔루션을 제안 ... 나는이 게시물에, 믿지 매우 유사하다. 내가 일하려고 노력해 왔지만 아직 실제로 작동하는 예를 보지 못한 것은 # 2입니다. 나는 이것이 가장 MVVM 친화적 인 접근 방식이라고 생각하며, 그 결과 가장 우아하고 ... 다시 한번, 나는 이것에 대해 아주 새롭다.

는 여기에 내부보고에 대한 것입니다 그냥 뭐 볼 스눕 다운로드

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

내 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을 사용하고 ...입니다. 나는 다양한 정도의 실패로 몇 가지 다른 방법을 시도했다.

주석 처리 된 부분은 내가 목표를 달성하려고했던 이전 방법입니다. 거기에 문제가 발생했습니다 ... "참조로 바인딩을위한 소스를 찾을 수 없습니다 'elementname = Field'"그러나 TextBlock은 Snoop을 사용하여 이름이 IS 필드임을 보여줍니다.

저는 현재 텍스트 블록에 로컬 네임 스코프가 있고 이름이 Field라는 것을 알 수 있습니다. 이것이 내가 기대하고 바라는 바입니다. ContextMenu 값은 올바른 2 개의 항목이있는 ContextMenu가 있음을 보여줍니다. 그래서 ContextMenu를 클릭하면 어떻게 보이고 낮추는지를 볼 수 있으며 ContextMenu에는 DataContext가 없다는 것을 볼 수 있습니다.

위의 사항에 대한 도움과 지침은 유용 할 것입니다. 내가 여기서 무엇을 놓치고 있는지 정확히 알지 못한다. 나는 주변을 둘러 보았는데 누군가가이 작업을하는 데 가까워 질 때마다 "해결 방법"또는 다른 방법으로 작업을 수행하고 결코 작동하지 않는다고 언급했습니다. 이 일을 할 수있는 능력이 있어야합니다 ... 나는 누락 된 조각을보기에는 너무 새롭다.

진정한 MVVM 방식으로 할 수 있다는 것을 알고 있습니다 ... 맞습니까?

답변

1

브라이스, 주요 문제는 ContextMenus가 표준 시각적 트리의 일부가 아니며 PlacementTarget 속성을 통해 유일한 실제 연결입니다. 따라서 일반적으로 가능한 한 빨리 연결하는 것이 가장 좋습니다. 그래서 ...

는 뷰 모델

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

그리고 MainWindow를

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

그리고 기본 VieWModel과 대화하는 멋지게 동작하는 ContextMenu를 얻어야합니다.

관련 문제