为什么亲属的约束力随机找不到来源?

发布于 2025-01-26 07:43:45 字数 4458 浏览 3 评论 0原文

我需要有人向我解释为什么两个绑定随机未能找到绑定。即使我精确地重复一遍又一遍地重复完全相同的2步,它们在失败和工作之间切换:(启动应用程序,导航到页面。开始应用程序,导航到页面等)。我可能会排5次失败,然后它可以工作,然后再失败7次,然后工作两次等。

这是VS输出窗口中的“失败”的样子,

System.Windows.Data Warning: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyCompany.Controls.LayerView, AncestorLevel='1''. BindingExpression:Path=ScanHeight; DataItem=null; target element is 'Path' (Name=''); target property is 'Data' (type 'Geometry')
System.Windows.Data Warning: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyCompany.Controls.LayerView', AncestorLevel='1''. BindingExpression:Path=ScanWidth; DataItem=null; target element is 'Path' (Name=''); target property is 'Data' (type 'Geometry')

这是绑定。我想使用包含绑定的控件的属性,因此我使用reacsimenceource findanceStor

<ctrl:LayerView x:Name="MainLayerView">
    <ctrl:LayerView.Layers> 
        <Path>
            <Path.Data>
                <MultiBinding Converter="{StaticResource CvtGuideOption}">
                    <!-- These fail to find the LayerView, but only *sometimes* -->
                    <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="ScanHeight"/>
                    <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="ScanWidth"/>
                </MultiBinding>
            </Path.Data>
        </Path>
    </ctrl:LayerView.Layers>
</ctrl:LayerView>

我可以使用这些始终工作或永远无法工作,但是 随机? (我尝试使用elementName而不是relativeancestor绑定,但效果是相同的。随机。)

最后,我偶然发现了一种方法(如下),似乎可以解决这个问题。但是我不知道我是否可以信任它。

<ctrl:LayerView x:Name="MainLayerView">
    <ctrl:LayerView.Layers>
         <Path Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ctrl:LayerView}}}">
            <Path.Data>
                <MultiBinding Converter="{StaticResource CvtGuideOption}">
                    <Binding RelativeSource="{RelativeSource Self}" Path="Tag.(ctrl:LayerView.ScanWidth)"/>
                    <Binding RelativeSource="{RelativeSource Self}" Path="Tag.(ctrl:LayerView.ScanWidth)"/>
                </MultiBinding>
            </Path.Data>
        </Path>
    </ctrl:LayerView.Layers>
</ctrl:LayerView>

如您所见,我的hack是首先将layerview源绑定到pathtag,然后使用 那个 是单个绑定的来源。到目前为止,这似乎总是找到来源。

但是,可以肯定的是,我已经解决了问题,我需要了解它是什么。

我唯一能做的摇摆物是,这与我要填写的layers集合的性质有关。这不是depentencyProperty。我正在尝试模仿什么itemscontrol.items做什么。这可能是一个因素吗?

附加信息: layerview控件看起来像这样。它很大,所以我在这里仅显示相关位。

// Custom control with a collection of layers and two Dependency properties.

public class LayerView : MultiSelector
{         
    // Layers property is not a DependencyProperty.  Just a public
    // Collection of objects.  This is me trying to mimic how ItemsControl 
    // implements its "Items" property  
    private Collection<object>? _layers;
    [Bindable(true), Category("Content")]
    public Collection<object> Layers => _layers ??= new Collection<object>();


    public static readonly DependencyProperty ScanWidthProperty =
        DependencyProperty.Register(
            nameof(ScanWidth),
            typeof(double),
            typeof(LayerView),
            new FrameworkPropertyMetadata(
                2464.0, // Default width from camera
                FrameworkPropertyMetadataOptions.AffectsRender));

    public double ScanWidth
    {
        get => (double)GetValue(ScanWidthProperty);
        set => SetValue(ScanWidthProperty, value);
    }


    public static readonly DependencyProperty ScanHeightProperty =
        DependencyProperty.Register(
            nameof(ScanHeight),
            typeof(double),
            typeof(LayerView),
            new FrameworkPropertyMetadata(
                2056.0, // Default image height from camera
                FrameworkPropertyMetadataOptions.AffectsRender));

    public double ScanHeight
    {
        get => (double)GetValue(ScanHeightProperty);
        set => SetValue(ScanHeightProperty, value);
    }
}

I need someone to explain to me why two bindings randomly fail to find the binding Source. They switch between failing and working even when I precisely repeat the exact same 2 steps over and over: (Start app, Navigate to page. Start app, navigate to page, etc). I might get 5 failures in row, then it works, then fails 7 more times, then works twice, etc.

Here is what "failure" looks like in the VS output window

System.Windows.Data Warning: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyCompany.Controls.LayerView, AncestorLevel='1''. BindingExpression:Path=ScanHeight; DataItem=null; target element is 'Path' (Name=''); target property is 'Data' (type 'Geometry')
System.Windows.Data Warning: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyCompany.Controls.LayerView', AncestorLevel='1''. BindingExpression:Path=ScanWidth; DataItem=null; target element is 'Path' (Name=''); target property is 'Data' (type 'Geometry')

Here are the bindings. I want to use properties of the control containing the binding, so I use RelativeSource FindAncestor

<ctrl:LayerView x:Name="MainLayerView">
    <ctrl:LayerView.Layers> 
        <Path>
            <Path.Data>
                <MultiBinding Converter="{StaticResource CvtGuideOption}">
                    <!-- These fail to find the LayerView, but only *sometimes* -->
                    <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="ScanHeight"/>
                    <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="ScanWidth"/>
                </MultiBinding>
            </Path.Data>
        </Path>
    </ctrl:LayerView.Layers>
</ctrl:LayerView>

I could live with these always working or never working, but randomly? (I tried using ElementName instead of RelativeAncestor binding but the effect was the same. Random.)

Finally, I stumbled upon an approach (below) that seems to get around this. But I don't know if I can trust it.

<ctrl:LayerView x:Name="MainLayerView">
    <ctrl:LayerView.Layers>
         <Path Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ctrl:LayerView}}}">
            <Path.Data>
                <MultiBinding Converter="{StaticResource CvtGuideOption}">
                    <Binding RelativeSource="{RelativeSource Self}" Path="Tag.(ctrl:LayerView.ScanWidth)"/>
                    <Binding RelativeSource="{RelativeSource Self}" Path="Tag.(ctrl:LayerView.ScanWidth)"/>
                </MultiBinding>
            </Path.Data>
        </Path>
    </ctrl:LayerView.Layers>
</ctrl:LayerView>

As you can see, my hack is to first bind the LayerView source into a the Tag of the Path and then use that as the source of the individual bindings. So far, this appears to always find the source.

But to be sure I've fixed the problem I need to understand what it was.

About the only WAG I can make is that this is somehow related to the nature of the Layers collection I'm filling out. It's not a DependencyProperty. I'm trying to mimic what ItemsControl.Items does. Could that be a factor?

Additional Info: The LayerView control looks like this. It's large so I've shown only the relevant bits here.

// Custom control with a collection of layers and two Dependency properties.

public class LayerView : MultiSelector
{         
    // Layers property is not a DependencyProperty.  Just a public
    // Collection of objects.  This is me trying to mimic how ItemsControl 
    // implements its "Items" property  
    private Collection<object>? _layers;
    [Bindable(true), Category("Content")]
    public Collection<object> Layers => _layers ??= new Collection<object>();


    public static readonly DependencyProperty ScanWidthProperty =
        DependencyProperty.Register(
            nameof(ScanWidth),
            typeof(double),
            typeof(LayerView),
            new FrameworkPropertyMetadata(
                2464.0, // Default width from camera
                FrameworkPropertyMetadataOptions.AffectsRender));

    public double ScanWidth
    {
        get => (double)GetValue(ScanWidthProperty);
        set => SetValue(ScanWidthProperty, value);
    }


    public static readonly DependencyProperty ScanHeightProperty =
        DependencyProperty.Register(
            nameof(ScanHeight),
            typeof(double),
            typeof(LayerView),
            new FrameworkPropertyMetadata(
                2056.0, // Default image height from camera
                FrameworkPropertyMetadataOptions.AffectsRender));

    public double ScanHeight
    {
        get => (double)GetValue(ScanHeightProperty);
        set => SetValue(ScanHeightProperty, value);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文