tags:

views:

3501

answers:

1

I have a WPF window, with multiple ListBox controls on it, all sharing the same style that I've simplified here:

   <Style x:Key="listBox" TargetType="{x:Type ListBox}">
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Border BorderBrush="Black">
                        <StackPanel Orientation="Horizontal" >
                            <TextBlock Text="{Binding Path=name}" />
                            <TextBlock Text="{Binding Path=text}" />
                            <TextBlock Text="id:" />
                            <TextBlock x:Name="_idTextBlock" Text="{Binding Path=id}" />
                            <Button Name="btnGet" CommandParameter="{Binding Path=id}" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

And here is an example of one of the ListBox controls using that style:

<ListBox x:Name="lbCampaigns" Button.Click="lbCampaigns_Click" ItemsSource="{Binding}" Style="{StaticResource listBox}" />

How can I set the Content of the Button control (btnGet) from within the parent ListBox?

I know what text I want the button to display at design time for each ListBox on the Window. (i.e. I don't need to bind it to the ListBox ItemsSource). I see that I can define the child control's events (see the Button.Click definition), but it doesn't appear that I can set the child control's properties in the same manner.

Any ideas? Thanks!

+4  A: 

Your setting of Button.Click isn't assigning the event handler to the Button. It's assigning it to the ListBox. It works because of WPF's routed event system.

If you want the Button to take on a value set at the level of the ListBox, one option in this case is to use a Binding with a RelativeSource:

<Button Content="{Binding Tag, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}"/>

In this case I've just hijacked the Tag property, which you can specify as follows:

<ListBox Tag="This is the button's content" .../>

Another option is to use an inherited attached property. For example:

<Button Content="{Binding local:MyClass.MyAttachedProperty}"/>

And then:

<ListBox local:MyClass.MyAttachedProperty="This is the button's content"/>

Finally, if you were templating the ListBox itself, you can "reach out" and bind to a property of the control you're templating using a TemplateBinding:

<Button Content="{TemplateBinding Tag}"/>

Of course, this technique is generally used with properties specifically declared on the templated control. For example, you could subclass ListBox and add your own ButtonContent property. Then, in your template you could reach out and bind to that property from the Button.

HTH, Kent

Kent Boogaart
Hi Kent, thanks for your help. Is there a typo in your FindAncestor code snippet?When I copy paste it into my button content property, I get a "AncestorType must be specified for RelativeSource in FindAncestor mode." error.I'll keep looking, but thought I'd mention it, in case you can help more.:)
Scott Ferguson
bah, looks like a VisualStudio error. I did a solution rebuild, and the error went away! Thanks for your help.
Scott Ferguson
Yeah, that's a common error when pasting a binding with a relativesource. I have it all the time.
Denis Troller
@Scott: you're welcome. I just did some edits to my post to make it a little clearer and comprehensive.
Kent Boogaart