2012-01-27 6 views
4

の情報を特定の方法で取得する(この質問では重要ではありません)custom markup extensionがあります。カスタムMarkupExtensionでFreezableを処理する方法は?

視覚的または論理的なツリーの一部ではない要素でこのマークアップ拡張を使用するまでは、すべてうまくいきます。私の特定の例では、要素InputBindingsにあります。このシナリオでは、FrameworkElementDependencyObjectとして取得する代わりに、FreezableKeyBinding)を取得します。

コードでDataContextにアクセスするにはどうすればよいですか?

私のXAMLコード:私は通常私のDataContext取得私のカスタムマークアップ拡張機能で

<UserControl.InputBindings> 
    <KeyBinding 
     Key="CapsLock" 
     Command="{wtc:CommandBinding {x:Static b:Commands.OpenTimeLine}}" /> 
</UserControl.InputBindings> 

コード:

protected override object ProvideValue(
    DependencyObject dependencyObject, 
    DependencyProperty dependencyProperty) 
{ 
    if (dependencyObject is Freezable) 
    { 
     // TODO: How to handle freezable? 
    } 

    _frameworkElement = dependencyObject as FrameworkElement; 
    if (_frameworkElement == null) 
    { 
     throw new InvalidImplementationException(
      "The DataContextBinding may only be used on framework elements."); 
    } 

    if (!_dataContextChangedHooked) 
    { 
     _frameworkElement.DataContextChanged += DataContextChanged; 
     _dataContextChangedHooked = true; 
    } 

    return ProvideValue(_frameworkElement.DataContext); 
} 

ソースコード全体は、同様にオンラインです。私は、マークアップ拡張のためのかなりのクラス階層を持っています。ここで

AbstractMarkupExtensionAbstractDependencyPropertyBindingExtensionAbstractDataContextBindingExtensionCommandBindingExtension

+1

これは難しいかもしれませんが、私はその物語のロジックが内部であることを知っています。 –

答えて

2

驚くほど簡単です。あなたが探しているDataContextがルートオブジェクトのDataContextと同じであれば、単純にIRootObjectProviderを使うことができます。このプロバイダーはIServiceProviderからアクセスでき、これは引数としてProvideValueとして渡されます。

var rootProvider = (IRootObjectProvider)ServiceProvider 
         .GetService(typeof(IRootObjectProvider)); 
_frameworkElement = rootProvider.RootObject as FrameworkElement; 

希望DataContextを見つけるために(LogicalChildren経由)ツリーを横断する必要があり、より複雑なシナリオがあるかもしれません。

0

厄介な反射の方法だろう。

var context = (FrameworkElement)typeof(DependencyObject) 
    .GetProperty("InheritanceContext", BindingFlags.NonPublic | BindingFlags.Instance) 
    .GetValue(dependencyObject, null); 
var datacontext = context.DataContext; 

FrameworkElementへのキャストがInheritanceContextは、タイプDependencyObjectでもInheritanceContextで、ない安全です通常Freezableが使用されているプロパティを宣言するオブジェクトで、FrameworkElementでない場合は再帰する必要がありますse)

+0

残念ながら、 'InheritanceContext'は' null'です。 –

+0

@StevenJeuris:残念ですが、これをテストしたところ、うまくいきました... –

+1

好奇心が強い、 'InputBindings'の下の' MarkupExtension'でもテストしましたか? –

関連する問題