2014-11-20 1 views
0

HierarchicalDataTemplates를 사용하는 TreeViewItem의 컨텍스트 메뉴와 함께 명령 패턴을 사용하고 있습니다. MainWindowViewModel (Window의 정적 리소스)에는 싱글 톤 객체를 표시하는 속성이 있으며이 객체는 명령을 나타내는 속성을 갖습니다. 명령을 올바르게 실행할 수 있지만 일부 명령은 TreeViewItem의 DataContext를 CommandParameter로 전달해야합니다.WPF 데이터 바인딩 ContextMenuItem의 CommandParameter를 TreeViewItem의 DataContext로 변환

다음은 구체적인 예입니다. 트리의 한 노드에는 개별 AnalysisMain 개체의 ObservableCollection에 바인딩 된 ItemsSource가 있습니다. 결과 서브 노드 각각에는 (다른 것들 중에서) Remove MenuItem이있는 ContextMenu (AnalysisController에 바인드 된 DataContext가 있음)가 있습니다. Remove MenuItem의 Command 속성은 AnalysisController 싱글 톤 개체의 CommandRemove 명령에 바인딩됩니다. 그러나 이렇게하려면 CommandParameter를 트리의 하위 노드에 대한 DataContext 역할을하는 AnalysisMain 개체에 바인딩해야합니다.

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TreeViewItem', AncestorLevel='4''. BindingExpression:Path=DataContext; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')

: 나는의 ContextMenu를 열 때, 나는 출력 창에 다음과 같은 얻을

<HierarchicalDataTemplate DataType="{x:Type vmAnalysis:AnalysisMain}"> 
    <WrapPanel Orientation="Horizontal"> 
     <Image Source="Analysis\Icon_Analysis_Main_16_Normal.png" Margin="0,0,2,0" Width="16"/> 
     <TextBlock Text="{Binding TreeViewTitle}"> 
      <TextBlock.ContextMenu> 
       <ContextMenu DataContext="{StaticResource mainWindowViewModel}"> 
        <MenuItem Header="Remove" Command="{Binding Path=AnalysisController.CommandRemove}" 
           CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}, AncestorLevel=4}, Path=DataContext}"> 
        </MenuItem> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </WrapPanel> 
</HierarchicalDataTemplate> 

AncestorLevel 설정하지 않고 : 나는 TreeViewItem로 설정 AncestorType와의 DataContext로 설정 패스와 함께 RelativeSource를 사용하여 시도

AncestorLevel에 대해 여러 값을 사용하지 않으려 고 시도했습니다.

Christian Mosers WPF Inspector의 시각적 트리를 검사하면서 시각적 트리의 컨텍스트 메뉴가 표시되지 않습니다. TreeViewItem은 DataContext 개체를 보여 주지만. 나는 그것에 바인딩하기 위해 그것을 "탐색"하는 방법이 필요합니다. 대안으로


, 나는 혼자의 ContextMenu의 DataContext를 떠나 다시 AnalysisController을 가리의 소스를 바인딩 명령을 설정 노력했다. 또한이 명령을 실행하기 위해 작동하지만 나는 CommandParameter의 TreeViewItem의 DataContext에 결합 할 수 아니다 : 나는 또한 단지 CommandParameter는 = "{바인딩}"도 작동하지 않는 사용하여 시도했다

<ContextMenu> 
    <MenuItem Header="Remove" Command="{Binding Source={StaticResource mainWindowViewModel}, Path=AnalysisController.CommandRemove}" 
       CommandParameter="{Binding Source={RelativeSource Self}, Path=DataContext}"> 
    </MenuItem> 
</ContextMenu> 

. (두 경우 모두 매개 변수로 null을 보내면 출력 창에 경고/오류가 기록되지 않습니다.) 편집 :이 문제가있는 다른 사용자에게는 두 번째 옵션이 처음부터 운명 지어졌습니다. 왜냐하면 실수로 Source = {RelativeSource Self}. TreeItem이 아니라 MenuItem을 참조합니다. 그러나 AncestorType/AncestorLevel로 변경하면 아무런 차이가 없습니다.

+0

내가 관련 정확한 버그에 대한 잘못 될 수있다 'CommandParameter' 바인딩에, 사실 매개 변수가'CanExecute' (즉 바인딩이 작동하지 않음) 내에서 null이지만'Execute' 콜백 내에서 매개 변수가 OK가 전달됩니다. 이전에 게시 한 코드의 경우 출력 창을보고 오류가 있는지 확인할 수 있습니다. –

+0

CanExecute를 검사하여 항상 true를 반환하도록하고 매개 변수가 여전히 null입니다. – Tim

답변

1

는 그런 다음이 바인딩으로 PlacementTarget.DataContext을 사용하십시오 RelativeSourceContextMenu에 할 당신의 MenuItemPlacementTargetContextMenu

<Setter Property="ContextMenu"> 
     <Setter.Value> 
      <ContextMenu 
     DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"> 
      </ContextMenu> 
     </Setter.Value> 
</Setter> 

의 재산을 사용할 필요가 귀하의 CommandParameter

+0

속성을 설정하는 것보다 Setter를 사용해야합니까? (나는 Setters를 Triggers와 함께 사용할 때만 익숙하다.) 다음은 내가 끝낸 것이다. (ContextMenu에서) DataContext = "{Binding PlacementTarget.{RelativeSource AncestorType = {x : Type ContextMenu}}, Path = PlacementTarget.DataContext} " – Tim

+0

@Tim 당신은 직접 Property를 사용할 수 있습니다. 방금 스타일을 사용하는 스 니펫이 있습니다. –

+0

누구든지 투표를했는데 왜 내게 알려 주실 수 있습니까? –