从父控件设置嵌套WPF控件属性

从父控件设置嵌套WPF控件属性

问题描述:

我有一个WPF窗口,上面有多个列表框控件,并共享同一个风格,我在这里简单:

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}" />

如何从父列表框中设置Button控件(btnGet)的内容?

我知道我想要的按钮显示在设计时对窗口中的每个列表框的文本内容。 (即我并不需要把它绑定到ListBox的ItemsSource)。我看到,我可以定义子控件的事件(见Button.Click定义),但它不会出现,我可以以同样的方式设置子控件的属性。

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.

任何想法? 谢谢!

Button.Click 的设置不分配事件处理程序的按钮。它把它分配给列表框。它的工作原理是因为WPF的路由事件系统。

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.

如果你想在按钮来取定为列表框,一个选项的水平值这种情况下是使用绑定的RelativeSource

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}"/>

然后:

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

最后,如果你是模板化列表框本身,就可以伸手,并使用 TemplateBinding :

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}"/>

当然,这种技术一般用于对模板的控制特别声明的属性。例如,你可以继承列表框并添加自己的 ButtonContent 属性。然后,在你的模板,你可以伸手从按钮绑定到该财产

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.