Search code examples
xamlmultibinding

how to use Multibinding.StringFormat on Fill property of a rectangle?


I've created an ItemControl with a dataTemplate that contains a rectangle that will be colorized based of the ItemsSource. The date being fed to my application is a color hex code that does not contain the hash sign (#). Just a 6-character string. To get the color to show up correctly i need to format the 6-character string with the # in front of it. exp #A31F34

Here's the XAML

<DataTemplate x:Key="ColorSequenceSwatchPreviews">
    <Rectangle Name="ColorSwatch" Height="20" Width="120" RadiusX="3" RadiusY="3" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,3,0,3">
        <Rectangle.Style>
            <Style TargetType="{x:Type Rectangle}">
                <Setter Property="Fill">
                    <Setter.Value>
                        <MultiBinding>
                            <MultiBinding.StringFormat><![CDATA[#{0}]]></MultiBinding.StringFormat>
                            <Binding Path="InnerXml" Mode="OneWay" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Style>
        </Rectangle.Style>
    </Rectangle>

I'm using a MultiBinding.StringFormat to format the string into a Hexcode properly, but am stumped as to why the fill of the rectangle is not colorizing.

I am able to get the rectangle to colorize if I do the MultiBinding with a TextBox, then bind the rectangle's fill property to the Text property of the textBox. However, I would much prefer binding directly from the rectangle's fill property like in my first example since it is cleaner.

<DataTemplate x:Key="ColorSequenceSwatchPreviews">
<StackPanel Orientation="Horizontal" Margin="0,3,0,3" VerticalAlignment="Center" HorizontalAlignment="Left">
    <TextBox x:Name="Hexcode" Visibility="Collapsed">
        <TextBox.Text>
            <MultiBinding>
                <MultiBinding.StringFormat><![CDATA[#{0}]]></MultiBinding.StringFormat>
                <Binding Path="InnerXml" Mode="OneWay" />
            </MultiBinding>
        </TextBox.Text>
    </TextBox>
    <Rectangle Name="ColorSwatch"  Height="20" Width="120" RadiusX="3" RadiusY="3" VerticalAlignment="Center" HorizontalAlignment="Left">
        <Rectangle.Style>
            <Style TargetType="{x:Type Rectangle}">
                <Setter Property="Fill" Value="{Binding ElementName=Hexcode,Path=,Mode=OneWay}" />
            </Style>
        </Rectangle.Style>
    </Rectangle>
</StackPanel>

Is there a way to get the first example to work or am i stuck with using the code from the second example?


Solution

  • This can be achieved far more easily using a Converter. You don't even need MultiBinding for it. Simple Binding with a Converter should do it:

    Here is the converter:

    <ValueConversion(GetType(String), GetType(SolidColorBrush))>
    Public Class HexToBrushConverter
      Implements IValueConverter
    
      Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
        Return DirectCast(New BrushConverter().ConvertFrom("#" & value.ToString()), SolidColorBrush)
      End Function
    
      Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
        Return Nothing
      End Function
    End Class
    

    All you need to do now is to create an object of the converter in your Resources section:

    <local:HexToBrushConverter x:Key="HexToBrushConverter" />
    

    (local is the namespace of your project where you define this converter class)

    and then use it in the Fill property:

    <Rectangle Fill="{Binding ElementName=Hexcode, Path=, Mode=OneWay, Converter={StaticResource HexToBrushConverter}}" />