我遇到一种情况,需要使用here所述的技术来解决绑定是指RelativeSource的绑定。我正在使用自定义标记扩展名,以允许将实际的Binding对象分配给DependencyProperty,但是不幸的是,当我尝试对Value中的DummyDO应用绑定时,它试图找到我的路径(例如在与Background等效标识的RelativeSource上的DummyDO)(不存在)。

我希望我可以通过存储传递到serviceProviderProvideValue属性并使用

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


从标记扩展在稍后的位置,但这会导致一个非常奇怪的null引用异常,其中没有可访问的null(我猜是某个引用已经以某种方式无效)。

另一种方法是在我的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传递的Binding对象)

标记扩展

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); }
}

最佳答案

是的,尚未能够精确地解决此问题,但确实根据以下方法使用了一种解决方法:


{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;



为我提供了所需的信息,但由于它无法回答问题,因此我暂时不接受此答案-只是为其他类似情况的人提供了一种解决方法。如果有人对为什么“标记扩展”方法不起作用有答案,我仍然会非常感兴趣。

关于c# - 如何在代码中评估RelativeSource对象以提供等效的有效Source,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27568421/

10-13 03:14