How may my Style Setter get at the DataContext of the of the element whose style is being set?

80 Views Asked by At

This seems like it should be simple as pie but I can't figure it out.

I am trying to change a working Style Setter for a "Fill" property on an element to actually declare a SolidColorBrush object in XAML in the Setter.Value. Unfortunately, in my brush declaration, I cannot seem to "get at" the DataContext of the very object whose Fill I am attempting to set. How may do I do this?

Below is the Style with setter. It uses a converter that takes an enum value ("Usage") and returns a Color value. The converter is fine but the binding fails because it cannot find the object.

<core:UsageToColorConverter x:Key="CvtUsageToColor"/>

<Style x:Key="RegionBandStyle" 
       TargetType="{x:Type tk:CartesianPlotBandAnnotation}">

    <!--  Help Intellisense show us the correct bindings when coding  -->

    <d:Style.DataContext>
        <x:Type Type="gci:IProfileRegion" />
    </d:Style.DataContext>


    <Setter Property="Fill">
        <Setter.Value>
            <SolidColorBrush >
                <SolidColorBrush.Color>
                    <!-- THIS BINDING FAILS:  It cannot find the "ancestor" CartesianPlotBandAnnotation
                         in order to get at its DataContext
                    -->
                    <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type tk:CartesianPlotBandAnnotation}}" 
                        Path="DataContext.(gci:IProfileRegion.Usage)"
                        Converter="{StaticResource CvtUsageToColor}"/>
                </SolidColorBrush.Color>
            </SolidColorBrush>
        </Setter.Value>
    </Setter>

</Style>

The binding fails with this message:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Telerik.Windows.Controls.ChartView.CartesianPlotBandAnnotation', AncestorLevel='1''. BindingExpression:Path=DataContext.Usage; DataItem=null; target element is 'SolidColorBrush' (HashCode=39731869); target property is 'Color' (type 'Color')

I suppose this makes sense. My dim understanding is that Brush is not in the visual (or logical) tree, right? So it can't find an ancestor? Is that the reason?

The original version of this Setter worked but it was much simpler. It just used a similar converter that returns a SolidColorBrush instead of a color:

    <Setter Property="Fill"  Value="{Binding Usage, Converter={StaticResource CvtUsageToBrush}}"/>

This worked fine but unfortunately (for unrelated reasons), I need to do things the other way; I need to declare the Brush explicitly myself using Property Element Syntax

Can someone tell me what binding voodoo I need here to get at the DataContext of the CartesianPlotBandAnnotation in my SolidColorBrush color binding?

(This is the sort of Binding issue that makes my head spin no matter how many times I read up on the Logical and Visual trees. My searches keep bringing up related topics but not the one I want. )

1

There are 1 best solutions below

1
Drreamer On

The FindAncesstor mode of the RelativeSource may be used to find a parent item in the Visual Tree. However, this is not the case. The brush color should inherit the element data context. Try to remove the RelativeSource setter at all. Also, are you sure that the Usage is the attached property? If not, simply set "Usage" in the Path. If this does not help, at least you will get a new error message saying which object is actually provide in the DataContext of CartesianPlotBandAnnotation.

Update: In case of interface binding, it should be enough to set Path to "(gci:IProfileRegion.Usage)". I have just tested this code and confirm that it works correctly: https://github.com/Drreamer/ColorInterfaceBinding If it does not work in your project, please clarify what exception is raised in this case. It helps to find the exact cause of the issue.