Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a MultiBinding with TemplateBindings

I am making a custom control in WPF. I am still learning the ins-and-outs of what a TemplateBinding is (used a lot in custom controls).

One think I am noticing is that I can't seem to use a TemplateBinding inside of a MulitBinding.

When I try this:

<ComboBox.ItemsSource>
    <MultiBinding Converter="{StaticResource MyMultiConverter}">
        <Binding ElementName="PART_AComboBox" Path="SelectedItem"/>
        <TemplateBinding Property="MyListOne"/>
        <TemplateBinding Property="MyListTwo"/>
    </MultiBinding>
</ComboBox.ItemsSource>

I get this error:

The value "System.Windows.TemplateBindingExpression" is not of type "System.Windows.Data.BindingBase" and cannot be used in this generic collection.
Parameter name: value

Am I missing something? Is there a way to make this work?

This is the workaround I have going, but it is kind of a hack:

<ListBox x:Name="ListOne" 
         ItemsSource="{TemplateBinding MyListOne}" 
         Visibility="Collapsed" />
<ListBox x:Name="ListTwo" 
         ItemsSource="{TemplateBinding MyListTwo}"
         Visibility="Collapsed" />

<ComboBox.ItemsSource>
    <MultiBinding Converter="{StaticResource DictionaryFilteredToKeysConverter}">
        <Binding ElementName="PART_TextTemplateAreasHost" Path="SelectedItem"/>
        <Binding ElementName="ListOne" Path="ItemsSource"/>
        <Binding ElementName="ListTwo" Path="ItemsSource"/>
    </MultiBinding>
</ComboBox.ItemsSource>

I bind the ListBoxes to the dependency property and then in my mulitbinding I do an element bind to the ItemsSource of the list boxes.

As I said above, this feels like a hack and I would like to know if there is a correct way to do a MultiBinding with a TemplateBinding as one of the components.

like image 257
Vaccano Avatar asked Jan 15 '13 16:01

Vaccano


1 Answers

You could use:

<Binding Path="MyListOne" RelativeSource="{RelativeSource TemplatedParent}"/>

TemplateBinding is really just a short-hand, optimized version of the above. It is very strict in where and how it can be used (directly inside template without hierarchical path et cetera).

The XAML compiler is still pretty rubbish at giving decent feedback about these kind of issues (at least in 4.0, not tested 4.5 specifically for this). I just now had this XAML:

<ControlTemplate TargetType="...">
    <Path ...>
        <Path.RenderTransform>
            <RotateTransform Angle="{TemplateBinding Tag}"/>
        </Path.RenderTransform>
    </Path>
</ControlTemplate>

It compiled and executed fine but was not binding the value in Tag to the rotation angle. I snooped and saw that the property was bound, but zero. Intuitively (after years of dealing with this annoyance) I changed it to this:

<ControlTemplate TargetType="...">
    <Path ...>
        <Path.RenderTransform>
            <RotateTransform Angle="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}"/>
        </Path.RenderTransform>
    </Path>
</ControlTemplate>

And it worked fine.

like image 120
Kent Boogaart Avatar answered Sep 28 '22 03:09

Kent Boogaart