2

I tried to create a custom control, having a semitransparent rounded background:

<Canvas>
    <TextBlock x:Name="StopText" Text="Some test text"/>
    <Rectangle Fill="SkyBlue"
               Width="{Binding Source=StopText, Path=ActualHeight}" 
               Height="20"  
               RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>

The problem is that I can't, probably, bind to the ActualHeight/ActualWidth properties, cause they are not dependency ones.

What to do to mantain the rectangle and textbox of same size?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
serhio
  • 28,010
  • 62
  • 221
  • 374

1 Answers1

10

The correct binding is to use ElementName, not Source, when binding to another element:

<Canvas>
    <TextBlock x:Name="StopText" Text="Some test text"/>
    <Rectangle Fill="SkyBlue"
               Width="{Binding ElementName=StopText, Path=ActualHeight}" 
               Height="20"  
               RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>

Also, you do realize that you are binding the width of the Rectangle to the Height of the TextBlock, right?

If this is really the way you want to set up your control, you will want to bind the Rectangle's Width to the TextBlock's ActualWidth, and Height to ActualHeight.

UPDATE Per the comments below, here is an implementation using a Grid with no binding:

<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <TextBlock x:Name="StopText" Text="Some test text"/>
    <Rectangle Fill="SkyBlue"
               HorizontalAlignment="Stretch"
               VerticalAlignment="Stretch"  
               RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Grid>

Grid and Canvas use different layout systems, and since you aren't using the functionality the Canvas provides, Grid is the better choice.

The big difference in the child elements is that the Rectangle now just uses Horizontal and VerticalAlignment to Stretch across the entire Grid, instead of worrying about the sizes of anything.

Community
  • 1
  • 1
Wonko the Sane
  • 10,623
  • 8
  • 67
  • 92
  • Good observation about ElementName. What If I would like to bind it to the Canvas itself(the main element of the UserControl). What should I set? – serhio Sep 24 '10 at 13:23
  • I would simply use a Grid instead of a Canvas, and then you don't need any binding at all. I'll update my answer. – Wonko the Sane Sep 24 '10 at 13:31
  • Hmm... With Canvas, I used `this.SetValue(Canvas.LeftProperty` to set the UserControl's location(inside the UserControl). How can I do now, with the Grid? – serhio Sep 24 '10 at 13:59
  • I believe even that there should be a way to stye the TextBox in order do not need "external" background rectangle... – serhio Sep 24 '10 at 14:04
  • #1.) You can still set the Canvas.LeftProperty, even though it is a Grid. #2.) Yes, you can certainly style a TextBlock (or TextBox, or any UIElement) by setting up a ControlTemplate using that UIElement's Template property. That's a (the?) fundamental basis of WPF. – Wonko the Sane Sep 24 '10 at 14:08
  • #1). I tested, and, unfortunately, this does not work, so I reset the Canvas as it was... – serhio Sep 24 '10 at 15:15
  • My mistake. Still, you could essentially get the same effect by specifying the margin. element.Margin = new Thickness(50d, 5d, 5d, 5d); – Wonko the Sane Sep 24 '10 at 15:23