0

In my WPF application I'm trying bind the background colour of a label to the colour of it's ancestor, however the coloured ancestor is couple of levels above.

What I have in my xaml code is this:

<Grid Background="Ivory" ClipToBounds="True" >
    <Canvas x:Name="SignalNames" 
            Panel.ZIndex="1"
            HorizontalAlignment="Left"
            Height="{Binding Path=ActualHeight, 
                             RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" >
        <Label Content="TestLabel">
            <Label.Background>
                <SolidColorBrush Opacity="0.618" 
                                 Color="{Binding Path=Background.Color, 
                                                 RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" />
            </Label.Background>
        </Label>
    </Canvas>
</Grid>

This works perfectly.


Now, I'd like to achieve the same effect (opaque background of the label) in the code, as I'm planning to place more labels and position them based on some calculated parameters.
I've came up wit the following code:

    public class OpaqueLabel : Label
    {
        public OpaqueLabel(Canvas canvas, string content, double position)
        {
            this.Content = content;
            canvas.Children.Add(this);

            Binding b = new Binding();
            b.Path = new PropertyPath("Background.Color");
            b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Grid), 2);

            Brush br = new SolidColorBrush();
            br.Opacity = 0.618;

            this.Background = br;
            BindingOperations.SetBinding(br, SolidColorBrush.ColorProperty, b);

            this.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            this.Width = this.DesiredSize.Width;
            this.Height = this.DesiredSize.Height;
            Canvas.SetTop(this, position);
        }
    }

This is not working. And here comes my question: why? How can I make it working? Is finding the ancestor the problem?

Mike
  • 1,225
  • 10
  • 21
  • 1
    why do you set Level 2 in code? make it 1 – ASh Aug 24 '18 at 10:06
  • I'm looking for the ancestor 2 levels above. Why it needs to be 1? By the way, this did the trick, thank you. – Mike Aug 24 '18 at 10:12
  • 1
    `` is level 1. xaml `{RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}` uses default level 1. your c# code was not equivalent. if you need level 2, you should fix xaml – ASh Aug 24 '18 at 10:14
  • 1
    levels apply to elements of the same type (AncestorType). there can be a lot of other nested elements between, but they do not participate in that numeration – ASh Aug 24 '18 at 10:15
  • 1
    As a note, you don't need to do this in code behind. In order *to place more labels and position them based on some calculated parameters* use an ItemsControl with a Canvas as ItemsPanel, e.g. like this: https://stackoverflow.com/a/22325266/1136211 – Clemens Aug 24 '18 at 10:29
  • @Ash, if I understand correctly, if I had a `Grid` in `Grid` and was looking for the higher one, I'd need to use 2 as level. Since I'm looking for the first ancestor of type `Grid`, I need 1 as level. Is that correct? – Mike Aug 24 '18 at 10:48
  • 1
    yes, that's correct. – ASh Aug 24 '18 at 11:14
  • @Clemens, thank you for the tip. It does move the logic to XAML which is nice, I don't feel like I've saved much of the lines of code with this solution. – Mike Aug 24 '18 at 11:49

0 Answers0