2014-12-19 34 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; 
    

让我得到我所需要的,但暂时不会接受这个答案,因为它不回答问题 - 只是为类似情况下的其他人提供解决方法。如果任何人有答案,为什么标记扩展方法不起作用,我仍然非常感兴趣。