ContextMenu가 표시되기 직전에 마우스 오른쪽 버튼을 클릭하여 WPF TreeView 노드를 선택하고 싶습니다.
WinForms의 경우 컨텍스트 메뉴 에서 클릭 한 Find 노드 와 같은 코드를 사용할 수 있습니다 . WPF 대안은 무엇입니까?
답변
트리가 채워진 방식에 따라 보낸 사람과 e.Source 값이 다를 수 있습니다 .
가능한 솔루션 중 하나는 e.OriginalSource를 사용하고 VisualTreeHelper를 사용하여 TreeViewItem을 찾는 것입니다.
private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);
    if (treeViewItem != null)
    {
        treeViewItem.Focus();
        e.Handled = true;
    }
}
static TreeViewItem VisualUpwardSearch(DependencyObject source)
{
    while (source != null && !(source is TreeViewItem))
        source = VisualTreeHelper.GetParent(source);
    return source as TreeViewItem;
}
답변
XAML 전용 솔루션을 원하는 경우 Blend Interactivity를 사용할 수 있습니다.
가정 TreeView가진 뷰 모델의 계층 컬렉션에 데이터 바인딩이다 Boolean재산 IsSelected과 String재산 Name뿐만 아니라라는 이름의 하위 항목의 컬렉션을 Children.
<TreeView ItemsSource="{Binding Items}">
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
      <TextBlock Text="{Binding Name}">
        <i:Interaction.Triggers>
          <i:EventTrigger EventName="PreviewMouseRightButtonDown">
            <ei:ChangePropertyAction PropertyName="IsSelected" Value="true" TargetObject="{Binding}"/>
          </i:EventTrigger>
        </i:Interaction.Triggers>
      </TextBlock>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>
두 가지 흥미로운 부분이 있습니다.
- 
TreeViewItem.IsSelected속성은 바인딩 된IsSelected뷰 모델에 대한 속성입니다.IsSelected뷰 모델 의 속성을 true로 설정하면 트리에서 해당 노드가 선택됩니다. - 
경우
PreviewMouseRightButtonDown(이 샘플 A의 노드의 시각적 부분 화재TextBlock)를IsSelected뷰 모델에 속성이 참으로 설정된다. 1로 돌아 가면 트리에서 클릭 한 해당 노드가 선택된 노드가되는 것을 볼 수 있습니다. 
프로젝트에서 Blend Interactivity를 얻는 한 가지 방법은 NuGet 패키지 Unofficial.Blend.Interactivity 를 사용하는 것 입니다.
답변
“item.Focus ();”사용 “item.IsSelected = true;”를 사용하여 100 % 작동하지 않는 것 같습니다. 않습니다.
답변
XAML에서 XAML에 PreviewMouseRightButtonDown 처리기를 추가합니다.
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <!-- We have to select the item which is right-clicked on -->
            <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/>
        </Style>
    </TreeView.ItemContainerStyle>
그런 다음 다음과 같이 이벤트를 처리합니다.
    private void TreeViewItem_PreviewMouseRightButtonDown( object sender, MouseEventArgs e )
    {
        TreeViewItem item = sender as TreeViewItem;
        if ( item != null )
        {
            item.Focus( );
            e.Handled = true;
        }
    }
답변
alex2k8의 원래 아이디어를 사용하여 Wieser Software Ltd의 비 비주얼, Stefan의 XAML, Erlend의 IsSelected 및 정적 메서드 Generic을 만드는 데 기여한 내용을 올바르게 처리합니다.
XAML :
<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
        <!-- We have to select the item which is right-clicked on -->
        <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown"
                     Handler="TreeViewItem_PreviewMouseRightButtonDown"/>
    </Style>
</TreeView.ItemContainerStyle>
뒤에 C # 코드 :
void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem treeViewItem =
              VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject);
    if(treeViewItem != null)
    {
        treeViewItem.IsSelected = true;
        e.Handled = true;
    }
}
static T VisualUpwardSearch<T>(DependencyObject source) where T : DependencyObject
{
    DependencyObject returnVal = source;
    while(returnVal != null && !(returnVal is T))
    {
        DependencyObject tempReturnVal = null;
        if(returnVal is Visual || returnVal is Visual3D)
        {
            tempReturnVal = VisualTreeHelper.GetParent(returnVal);
        }
        if(tempReturnVal == null)
        {
            returnVal = LogicalTreeHelper.GetParent(returnVal);
        }
        else returnVal = tempReturnVal;
    }
    return returnVal as T;
}
편집 : 이전 코드는이 시나리오에서 항상 잘 작동했지만 다른 시나리오에서는 LogicalTreeHelper가 값을 반환 할 때 VisualTreeHelper.GetParent가 null을 반환하므로이를 수정했습니다.
답변
거의 맞지만, 트리에서 비 시각적 요소 (예 :)를주의해야합니다 Run.
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
    while (source != null && source.GetType() != typeof(T))
    {
        if (source is Visual || source is Visual3D)
        {
            source = VisualTreeHelper.GetParent(source);
        }
        else
        {
            source = LogicalTreeHelper.GetParent(source);
        }
    }
    return source;
}
답변
클래스 핸들러를 등록하는 것이 트릭을해야한다고 생각합니다. 다음과 같이 app.xaml.cs 코드 파일에있는 TreeViewItem의 PreviewMouseRightButtonDownEvent에 라우트 된 이벤트 핸들러를 등록하기 만하면됩니다.
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        EventManager.RegisterClassHandler(typeof(TreeViewItem), TreeViewItem.PreviewMouseRightButtonDownEvent, new RoutedEventHandler(TreeViewItem_PreviewMouseRightButtonDownEvent));
        base.OnStartup(e);
    }
    private void TreeViewItem_PreviewMouseRightButtonDownEvent(object sender, RoutedEventArgs e)
    {
        (sender as TreeViewItem).IsSelected = true;
    }
}