2014-12-19 61 views
2

我有一種情況,即需要使用描述爲here的技術來解析綁定,其中綁定指向RelativeSource。我使用自定義標記擴展來允許我將實際綁定對象分配給DependencyProperty,但不幸的是,當我試圖對DummyDO中的Value應用綁定時,它試圖找到我的路徑(例如Background)等效標識RelativeSourceDummyDO,它不存在。如何在代碼中評估RelativeSource對象以提供有效的源代碼

我希望我也許可以通過存儲被傳遞到ProvideValueserviceProvider財產,並使用

return this.TargetBinding.ProvideValue((IProvideValueTarget)this.ServiceProvider); 

從在稍後的點標記擴展來解決這個問題,但是這導致非常奇怪的空引用異常,其中任何可訪問性爲空(我的猜測是一些引用已被無效)。

另一種方法是存儲屬性的實際來源我ProvideValue方法的過程中,然後創建的ProvideCurrentValue一個新的方法重新評估每DummyDO方法後綁定。我無法解決如何做到這一點!任何幫助將非常感激。下面

代碼:

XAML

<StackPanel> 
    <Button 
    h:ResponsiveBrush.CentreTrackBrush="True" 
    h:ResponsiveBrush.Binding="{e:PassBinding TargetBinding={Binding Background,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel}}}}" 
    > 
     <Button.Content>Try Me</Button.Content> 
    </Button> 
</StackPanel> 

(H:ResponsiveBrush是不相關的東西我們之後 - 這是我試圖附加的行爲,而關鍵的一部分這是在某些時候,它需要解決它通過PassBindingExtension已經通過綁定對象)

標記擴展

public class PassBindingExtension : MarkupExtension 
{ 
    public PassBindingExtension() { } 
    public PassBindingExtension(Binding targetBinding) 
    { 
     this.TargetBinding = targetBinding; 
    } 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     var valueGetter = serviceProvider as IProvideValueTarget; 
     if (valueGetter != null) 
     { 
      // Get the object. NB that this will evaluate to a 
      // BUTTON given the XAML above NOT a StackPanel as I was hoping 
      this.TargetObject = valueGetter.TargetObject; 
      this.TargetProperty = valueGetter.TargetProperty; 

      /* 
       Ideally around here I need to evaluate the object to which 
       this. TargetBinding refers around here so I can get the correct 
       value later. 
      */ 
     } 

     /* 
      Addendum: If I try the following at this point, my application vanishes into 
      oblivion 

      var oOriginalValue = this.TargetBinding.ProvideValue(serviceProvider); 

      Not sure if that's intended or not, but since I don't need to get the 
      original value, I just need the info to work out where the future value 
      should come from, I'm not too fussed. 
     */ 

     return this; 
    } 

    public object ProvideValueLate() 
    { 
     object oOut = null; 

     /* Somehow, here, I need to reliably obtain 
      the value of TargetProperty on the 
      RelativeSource that would be evaluated with 
      respect to TargetObject 
     */ 

     return oOut; 
    } 

    [ConstructorArgument("targetBinding")] 
    public Binding TargetBinding { get; set; } 

    public object TargetObject { get; set; } 

    public object TargetProperty { get; set; } 

    // Obsolete - doesn't work 
    public IServiceProvider ServiceProvider { get; set; } 

    // Was hoping this would let me sidestep the issue, but lamentably it doesn't 
    public object ProvideValueLate_Old() 
    {  return this.TargetBinding.ProvideValue((IProvideValueTarget)this.ServiceProvider); } 
} 
+0

顯示您的相關代碼......沒有代碼,您的話意味着很少。 – Sheridan

+0

我已經添加了標記擴展的代碼,以及我如何在XAML中使用它。基本思想是讓我能夠將h:ResponsiveBrush應用於任意刷子屬性,而不是例如。只是背景或邊界。 – tobriand

+0

我還應該指出,在編寫問題時,意圖是建立一個依賴Source而不是RelativeSource的新綁定,因此可以在DummyDO(從鏈接的文章中)中成功綁定。這可能仍然是一個不錯的解決方法,但是爲了可讀性,我還沒有完成一半的代碼來構建新的綁定。 – tobriand

回答

0

權,一直無法精確地工作了這一點,但還是設法用一種變通方法,基於以下幾點:

  • {Binding RelativeSource={RelativeSource Self}}通過標準的依賴屬性演算值爲對象的問題, Self可以是任何RelativeSource。
  • 因此,在附加的行爲上創建兩個屬性,一個用於我們想要屬性的對象,另一個用於屬性路徑。將它們稱爲SourceObject和SourcePath。
  • 使用下面的方法獲取現有值。這是在h:ResponsiveBrush的事件處理程序 - 我沒有設法使用標記擴展(這是我所喜歡的,但不能擁有所有...)的工作:

    string sourcePath = ((DependencyObject)sender).GetValue(SourcePathProperty); 
    DependencyObject sourceObject = ((DependencyObject)sender).GetValue(SourceObjectProperty); 
    Binding b = new Binding(sourcePath) {Source = sourceObject}; 
    RadialGradientBrush sourceBrush = DependencyInterpreter.EvalBinding(b) as RadialGradientBrush; 
    

讓我得到我所需要的,但暫時不會接受這個答案,因爲它不回答問題 - 只是爲類似情況下的其他人提供解決方法。如果任何人有答案,爲什麼標記擴展方法不起作用,我仍然非常感興趣。