WPF如何从DataTemplate访问控件

8

我有一个数据模板,里面包含一个网格以及网格内的一个组合框。

<DataTemplate x:Key="ShowAsExpanded">
        <Grid>                
            <ComboBox Name ="myCombo" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="5"
                      IsSynchronizedWithCurrentItem="True"
                      ItemsSource="{Binding}"
                      ItemTemplate="{StaticResource MyItems}">
                <ComboBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel />
                    </ItemsPanelTemplate>
                </ComboBox.ItemsPanel>
            </ComboBox>

        </Grid>
    </DataTemplate>

我有一个网格,通过样式引用该模板。
<Grid>
    <ContentPresenter Name="_contentPresenter" Style="{DynamicResource StyleWithCollapse}" Content="{Binding}" />
</Grid>

我该如何通过代码访问myCombo并设置其DataContext?
3个回答

31

Three ways which I know of.

1.Use FindName

ComboBox myCombo =
    _contentPresenter.ContentTemplate.FindName("myCombo",
                                               _contentPresenter) as ComboBox;

2.将Loaded事件添加到ComboBox中,并从那里访问它

<ComboBox Name ="myCombo" Loaded="myCombo_Loaded" ...

private void myCombo_Loaded(object sender, RoutedEventArgs e)
{
    ComboBox myCombo = sender as ComboBox; 
    // Do things..
}

3.在可视树中找到它

private void SomeMethod()
{
    ComboBox myCombo = GetVisualChild<ComboBox>(_contentPresenter);
}
private T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
    T child = default(T);
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

谢谢,非常有帮助,但Geert van Horrik的回答让我想到通过代码后台访问并不是正确的方式... - pdiddy

6

首先,我甚至找不到Resource(ShowAsExpanded)与ContentPresenter内部使用之间的关系。但是暂且假设DynamicResource应该指向ShowAsExpanded。

您不能也不应该通过代码访问组合框。您应该将数据上下文绑定到使用该样式的网格中。如果您不想这样做,您将不得不在运行时查找内容并搜索子组合框。


有趣。我对wpf还比较新。在网格上设置数据上下文,这会如何传播到模板中的组合框?另外,如果我的模板中有2个组合框,如果每个组合框都有不同的数据上下文,那么每个组合框的数据上下文应该如何绑定? - pdiddy
2
只要您没有显式地设置子级的数据上下文,数据上下文就会传播到子级。因此,如果在 Grid 上设置了数据上下文,则 ContentPresenter(以及所有下面的控件)将共享该数据上下文并可以绑定到它。 - Geert van Horrik
如果我的模板中有两个组合框需要通过两个不同的集合进行绑定,应该如何实现? - pdiddy
你可以创建一个包含两个集合的数据对象,然后将数据上下文设置为该对象的实例。然后,你可以将两个组合框绑定到正确的集合。 - Geert van Horrik
你的回答很有道理,将ContentPresenter绑定到不同的集合上也可以正常工作。但是如果我的数据模板包含一个ListView,我有时想要添加GroupDescriptions怎么办?据我所知,这只能在代码后台完成。 - Good Night Nerd Pride
我上面描述的问题可以通过在XAML中定义一个CollectionViewSource,并将应显示分组ListViewContentPresenter绑定到它来解决。即使DataTemplate中的ListView现在总是定义了一个GroupStyle,但只有绑定到CollectionViewSourceListViews才会显示分组。 - Good Night Nerd Pride

1

有没有关于如何在这种情况下使用FindName的示例? - Jeson Martajaya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接