Wpf – Pass the value of one control to a Converter to set the width on another control

bindingconvertersdata-bindingwpf

I want to set the width of a TextBlock based on the width of its container, minus the margins set on the TextBlock.

Here is my code:

<TextBlock x:Name="txtStatusMessages" 
           Width="{Binding ElementName=LayoutRoot,Path=ActualWidth }"
                   TextWrapping="WrapWithOverflow" 
           Foreground="White" 
           Margin="5,5,5,5">This is a message
</TextBlock>

And that works great except for the fact that the TextBlock is 10 units too big due to the Left and Right Margins bbeing set to 5.

OK, so I thought… Let's use a Converter. But I don't know how to pass the ActualWidth of my container control (SEE ABOVE: LayoutRoot).

I know how to use converters, and even converters with parameters, just not a parameter like… Binding ElementName=LayoutRoot,Path=ActualWidth

For example, I can't make this work:

Width="{Binding Converter={StaticResource PositionConverter},  
       ConverterParameter={Binding ElementName=LayoutRoot,Path=ActualWidth }}"

I hope I made this clear enough and hope that you can help because Google is no help for me tonight.

Best Answer

you're supposed to use the other control as the source, not the parameter. The parameter has to be a constant and in your case can be -5.

I'm not near VS at the moment so the syntax maybe inaccurate, however, it is something like:

Width="{Binding ElementName=LayoutRoot, Path=ActualWidth,
Converter={StaticResource PositionConverter}, ConverterParameter=-5}"

(The converter will receive -5 as a string and will have to convert it into a number before using it.)

From my experience it is better to use the OnXXXChanged callback of DependecyProperty XXX, and not bind controls within the same window/root control one to another. One of the reasons for this is that you may want to bind them to an external element later on.

Or alternatively, use multibinding:

<TextBlock>
    <TextBlock.Width>
        <MultiBinding Converter="{StaticResource yourConverter}">
            <MultiBinding.Bindings>
                <Binding /> <!-- Bind to parameter 1 here -->
                <Binding /> <!-- Bind to parameter 2 here -->
          </MultiBinding.Bindings>
        </MultiBinding>
    </TextBlock.Width>
</TextBlock>

and and a converter which converts the two parameters to the value you want.

Related Topic