2017-03-27 38 views
2

と呼ばれます。この問題は主にコンテキストメニューに関連しますが、私の特定のケースではTreeViewコントロールに関するものです。コンテキストメニューとしてのTreeViewアイテムのWPF選択は

TreeViewアイテムにはStackPanelが含まれています。そのStackPanelはStaticResource(これはContextMenuです)に割り当てられたContextMenuプロパティです。このContextMenuはICommandにつながり、したがってそのことを行います。

現在のところ、これは私が信じるデフォルトの動作ですが、TreeViewの項目を右クリックするとその項目は選択されません。これはWindowsでは一般的ですが、ここでは発生しません。私はそれが起こることを望む(しかし、私は方法を知らない)。

少しのフォローアップ情報:ツリービューで選択した項目があり、これがマウスの左クリックで変更されます。しかし、左クリックイベントではなく、むしろイベントは 'SelectedItemChanged'です。これは、私のデータコンテキスト(ビューモデル)で 'SelectedItem'をSelectedItemに設定する方法につながります。これはTreeViewの選択された項目が「読み取り専用」であるため、このようにしなければなりません。私はそれが手元に問題にどれだけ役に立つか分からないが、

このコードは、ここにある:

private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) 
    { 
     if (this.ScenesTreeView01 == null) 
      return; 

     if (this.ScenesTreeView01.DataContext == null) 
      return; 

     var DataContext = this.ScenesTreeView01.DataContext as ScenesViewModel; 

     if (e.NewValue is SceneViewModel) 
     { 
      DataContext.SelectedScene = (SceneViewModel)e.NewValue; 
     } 

     if (e.NewValue is CharacterViewModel) 
     { 

      DataContext.SelectedCharacter = (CharacterViewModel)e.NewValue; 
     } 
    } 

それは大丈夫、あなたが左クリックと言う場所があるとは思えないので、選択されたアイテムがここにあるので、右クリック(および左クリック)で選択したアイテムを割り当てるように指示するにはどうすればよいか分かりません。

どうすればいいですか?

編集:MVVMを使用しているので、RoutedPropertyChangedEventArgs eというパラメータを持つSelectedItemChangedのようなメソッドがあると、e.SourceはTreeViewItemではなく、自分のビューモデルに戻ってきます。あなたのSceneViewModelCharacterViewModelクラスとバインドにIsSelectedプロパティを追加することができ

TreeView.MouseRightButtonDown += Tv_MouseRightButtonDown; 

void Tv_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { 
    var tvItem = e.Source as TreeViewItem; 
    if (tvItem != null) { 
     tvItem.IsSelected = true; 
    } 
} 

答えて

0

迅速な解決策は、単純に、ツリービューののMouseRightButtonDownイベントを登録し、クリックがツリービューアイテムにあったかどうかを確認し、それを選択するかもしれませんスタイルを使用してTreeViewItemIsSelectedをこれらのプロパティに割り当てます。 PreviewMouseRightButtonDownはソースプロパティを設定するために、同じスタイルでは、その後、イベントハンドラをフックできます

<TreeView x:Name="treeView"> 
    <TreeView.Resources> 
     <Style TargetType="TreeViewItem"> 
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
      <EventSetter Event="PreviewMouseRightButtonDown" Handler="treeView_PreviewMouseRightButtonDown" /> 
      <Setter Property="ContextMenu"> 
       <Setter.Value> 
        <ContextMenu> 
         <MenuItem>1</MenuItem> 
        </ContextMenu> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </TreeView.Resources> 
</TreeView> 

private void treeView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    TreeViewItem tvi = sender as TreeViewItem; 
    CharacterViewModel cvm = tvi.DataContext as CharacterViewModel; 
    if (cvm != null) 
    { 
     cvm.IsSelected = true; 
    } 
    else 
    { 
     SceneViewModel svm = tvi.DataContext as SceneViewModel; 
     if (svm != null) 
      svm.IsSelected = true; 
    } 
} 

CharacterViewModelSceneViewModelクラスはINotifyPropertyChangedインタフェースを実装することを確認し、PropertyChangedを調達します新しいIsSelectedプロパティのセッターのイベント。

+0

申し訳ありません。私はこれが私のためにはうまくいかない理由を説明する編集を追加しました。私はMVVMを使用しているので、e.Sourceは私のViewModelのデータオブジェクトをTreeViewItemではなく参照しています。私の質問にそれを含めるべきだったのですが、もう一度私の謝罪ははっきりしないのです。 – TheFaithfulLearner

+0

SelectedItemChangedイベントまたはMouseRightButtonDownに対してのみこれを確認しましたか? Source/OriginalSourceは、実際にイベントを起こしたフレームワーク要素を常に指し示すと思っていました。 わからない場合は、SnoopやWPF Inspectorのようなツールを使用して、イベントの発生場所と処理場所を調べることができます。 とにかく、MVVMを使用している場合は、TreeViewItemのスタイルを作成し、そのIsSelectedプロパティをviewmodelの何かにバインドするよりクリーンなアプローチかもしれません。 – wilford

+0

私はこれが遅い応答であることを知っていますが、問題は同じでしたので、私はこの解決策を使用できません。しかし、答えに時間をとってくれてありがとう、 – TheFaithfulLearner

1

+0

私はそれが他のスレッドで私のために働いていないと言ったので、私は精巧に思った。私はあなたのコードの最初の部分を既存のTreeView.Resourceタグに入れました。また、コードの中に、あなたが言及している方法もあります。それは起動しませんが、XAMLに接続されているので、なぜ起動していないのかを判断する方法を確認する方法はわかりません。また、そこにコンテキストメニューがある理由を理解できません。私はすでにいくつかのコンテキストメニューを持っているので、それは必要ですか、彼らは大丈夫です。 – TheFaithfulLearner

+0

ちょっと男、すぐに更新しています。それは私のために働いていなかった理由は、私はすでに私のXAMLでそのタイプのスタイルを持っていたので、もう一つ持っていることができないことを知らなかったからです。だから私はあなたの部分を既存のものに入れています。それは何らかの理由を除いて、トップレベルの項目( 'シーン')の場合には一度メソッドが呼び出され、私は、サブレベルの項目(「文字」)をクリックします。だから私にこれを得るためにありがとう – TheFaithfulLearner

+0

複数の呼び出しの問題について:この場合。 'MouseRightButtonDown'を使うと' PreviewMouseRightButtonDown'よりも良いかもしれません。なぜなら、前者はツリーを下って行き、最初の呼び出しは偽陽性となり、後者は正しい 'TreeViewItem'で最初の呼び出しを行います。また、イベントを回避するために 'e.Handled = true'を設定してください。 – grek40

0

あなたはそれのために行動を使用することができます。

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Interactivity; 

public class SelectOnRMBBehavior : Behavior<FrameworkElement> 
{ 
    public static readonly DependencyProperty CurrentItemProperty = DependencyProperty.Register("CurrentItem", typeof(TreeViewItem), typeof(SelectOnRMBBehavior), new PropertyMetadata(null)); 

    public TreeViewItem CurrentItem 
    { 
     get 
     { 
      return (TreeViewItem)GetValue(CurrentItemProperty); 
     } 
     set 
     { 
      SetValue(CurrentItemProperty, value); 
     } 
    } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 

     AssociatedObject.PreviewMouseRightButtonDown += AssociatedObject_PreviewMouseRightButtonDown; 
    } 

    private void AssociatedObject_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     if (CurrentItem!=null) 
     { 
      CurrentItem.IsSelected = true; 
     } 
    } 

    protected override void OnDetaching() 
    { 
     AssociatedObject.PreviewMouseRightButtonDown -= AssociatedObject_PreviewMouseRightButtonDown; 

     base.OnDetaching(); 
    } 
} 

をしてからちょうどクリックされる要素にあなたの行動を置く(私はDataTemplateの中にコンテナを想定):

<StackPanel> 
    <i:Interaction.Behaviors> 
     <b:SelectOnRMBBehavior CurrentItem="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}}"/> 
    </i:Interaction.Behaviors> 
</StackPanel> 
関連する問題