WPF中FindAncestor绑定Release正常,Debug模式间歇性失效
我遇到一个费解的绑定错误:该绑定在Release模式下始终正常工作,但在Debug模式下,有时会通过FindAncestor无法找到数据源。
此绑定用于WPF Path的样式,该样式仅在Path位于名为LayerView的特定自定义控件内时使用。样式中3个查找父级LayerView对象的绑定会间歇性失效:
<Style x:Key="LayerViewGuidePathStyle" TargetType="{x:Type Path}"> <Setter Property="Data"> <Setter.Value> <MultiBinding Converter="{StaticResource CvtGuideOption}"> <Binding Source="{svc:ViewSettings}, Path=GuideOption}" /> <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="ScanWidth" Converter="{ctrl:LogValueConverter}"/> <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="ScanHeight" Converter="{ctrl:LogValueConverter}"/> <Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:LayerView}}" Path="SceneTransform" Converter="{ctrl:LogValueConverter}"/> </MultiBinding> </Setter.Value> </Setter> </Style>
绑定失效时会出现以下警告:
System.Windows.Data Warning: 4 : Cannot find source for binding with
reference 'RelativeSource FindAncestor,
AncestorType='MyControls.LayerView', AncestorLevel='1''.
BindingExpression:Path=ScanHeight; DataItem=null; target element is
'Path' (Name='GuidePath'); target property is 'Data' (type 'Geometry')
以下是LayerView中使用该样式的方式:
<ctrl:LayerView x:Name="MainLayerView" ItemsSource="{Binding Shapes}"> <ctrl:LayerView.Layers> <Path x:Name="GuidePath" Style="{StaticResource LayerViewGuidePathStyle}" /> </ctrl:LayerView.Layers> </ctrl:LayerView>
LayerView继承自MultiSelector,仅添加了一个非依赖属性Layers(类型为Collection<object>),设计思路是让用户在XAML中静态设置内容,最终将这些内容显示在控件的标准项上方:
public class LayerView : MultiSelector { static LayerView() { DefaultStyleKeyProperty.OverrideMetadata(typeof(LayerView), new FrameworkPropertyMetadata(typeof(LayerView))); } private Collection<object>? _layers; public Collection<object> Layers => _layers ??= new Collection<object>(); }
LayerView的ControlTemplate中,除了必备的ItemsPresenter,还添加了一个ItemsControl来显示Layers内容,作为不可命中测试的"覆盖层":
<ControlTemplate x:Key="LayerViewTemplate" TargetType="{x:Type gcl:LayerView}"> <Canvas x:Name="PART_MainCanvas" Background="Transparent"> <!-- 显示控件自身的项 --> <ItemsPresenter x:Name="PART_Items" /> <!-- 显示自定义Layers内容 --> <ItemsControl x:Name="PART_Layers" ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Layers}" IsHitTestVisible="False"/> </Canvas> </ControlTemplate>
我完全摸不着头绪,一般绑定问题要么持续成功要么持续失败,但这种间歇性失效的情况几乎像是竞态条件。想知道问题出在哪?是Layers属性类型不对,还是缺少某些关键特性?
内容的提问来源于stack exchange,提问作者Joe

