2016-11-02 10 views
0

私は次のコードWPF TransformToAncestorエラー

public partial class MyControl : UserControl 
{ 
    ... 
    private void UserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     if (DataContext is MyViewModel) 
     { 
      var vm = DataContext as CameraViewModel; 
      var p = Parent as FrameworkElement; 
      while (!(p is Window)) 
       p = p.Parent as FrameworkElement; 

      vm.GetTransform =() => TransformToAncestor(p); 
     } 
    } 

} 

を持っていると私のviewmodelで、私はコマンドハンドラのコードを持って、私のユーザーコントロールのボタンがクリックされたときに、実行されます。

public Func<GeneralTransform> GetTransform { private get; set; } 
private void OnMyCommand(object parameter){ 
    var p = GetTransform().Transform(new Point(0,0)); 
} 

しかし、上記のコードは動作しません、GetTransform()呼び出しは、私は上記の私のコードはすでにpは、コントロールのウィンドウの祖先であるが、なぜ私はまだ取得することが保証されると考え

The specified Visual is not an ancestor of this Visual. 

を言うようにこのエラー?

+0

例外は 'TransformToAncestor()'で発生するため、ソースがない場合は何も特定できません。例外が話している2つの「ビジュアル」は、どのようなオブジェクトインスタンスですか? 'GetTransform()'が実行されているとき、 'p'はWindowインスタンスではありませんか? – Jai

+0

@Jai 'UserControl_Loaded'のコードは、" this "の' Visual'がユーザコントロールで、 '指定された' 'Visual'は' Window'に到達するまで先祖列車を追跡して戻ったものです。これはデバッグでの観察と一致しているので、上記の主張を信頼します。 –

+0

Multi-Windowアプリケーションを実行していない場合に備えて、WPFアプリケーションのメインウィンドウでもあるApplication.Current.MainWindowを試してみてください。 –

答えて

0

@Brian Reichleのコメントのおかげで、理由を理解して解決しました。

タブコントロールの異なるタブで同じコントロールを使用している場合があります。

ご存じのとおり、常にアクティブなタブは1つだけです。これらのコントロールは、現在非アクティブなタブに属し、ウィンドウの祖先を持たない異なるビジュアルツリーに属します。私はWindowオブジェクトを把握するために論理ツリーをバックトラックが、thisオブジェクトがいくつか見えないタブに属し、そのWindowとしての視覚的な祖先を持っていないです。私の場合は

が、これは何が起こったのかです。

これを実現したら、解決策はLoadedイベントを添付せず、IsVisibleChangedイベントを添付します。

private void UserControl_IsVisibleChanged(object sender, 
     DependencyPropertyChangedEventArgs e) 
    { 
     if (!(bool)e.NewValue) 
      return; 
     if (DataContext is CameraViewModel) 
     { 
      SaveTransform(); 
     } 
     else Dispatcher.InvokeAsync(SaveTransform); 
    } 

    private void SaveTransform() 
    { 
     var vm = DataContext as CameraViewModel; 
     var w = VisualTreeHelper.GetParent(this) as FrameworkElement; 
     while (w != null && !(w is Window)) 
      w = VisualTreeHelper.GetParent(w) as FrameworkElement; 
     if (w != null) 
     { 
      vm.GetTransform =() => TransformToAncestor(w); 
     } 
    } 

注:IsVisibleChangedイベントの最初の火の中にデータコンテキストがまだ設定されていない可能性があります。したがって、上記のコードは後でSaveTransformコードを返さなければなりません。

関連する問題