如何从ControlTemplate中检索VisualChild

时间:2014-09-15 09:31:48

标签: wpf wpf-controls

我在.NET 3.5 SP1中有一个使用TabControl的WPF应用程序 我们有TabItems,而Styles又有TabItem来确定当前显示的项目 我们假设我们有<TabControl> <TabItem Header="Books"/> <TabItem Header="DVD's"/> ... </TavControl> 名为图书,现在图书将有三个显示阶段:
1.加载结果,
2.显示结果,
3.没有显示结果 - 即找不到任何结果。

TabItems

现在我有5个<TabItem Header="Books"> <Control> <Control.Resources> <Style TargetType="Control"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Control"> <ListView ItemsSource="{Binding Books}"/> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <!-- Assign different Visuals depending on the current state of the app, i.e. Loading, No results, results found <DataTrigger .../> </Style.Triggers> </Style> </Control.Resources> </Control> </TabItem> 让我们说代表&#34; DVD&#34;,&#34; Blu-Rays&#34;,&#34; CD&# 39; s&#34;,&#34;书籍&#34;和&#34;漫画&#34;。

TabItem

TextBlock下方,我有一个<TextBlock> <TextBlock.Text> <MultiBinding StringFormat="Displaying {0} records for your Shop ({1})" Converter="{StaticResource tstMVC}"> <Binding ElementName="Tc" Path="SelectedValue"/> <Binding Path="ShopId" FallbackValue="Liverpool"/> </MultiBinding> </TextBlock.Text> </TextBlock> 来显示当前找到的结果数量:

MultiBinding

转换器可供我查看ListView中传递的值 的 ISSUE:
用户选择标签项时,我想显示所显示项目的当前数字,但我无法找到{{1}中的Control因为那是TabItem的当前内容 我尝试过TabControl.SelectedItem,SelectedValue但仍然无法找到Current ItemsSource.Count。
提前致谢


更新
感谢@Sheridan和@pushpraj,我已经尝试了两种解决方案! 不幸的是我还没有使用它们中的任何一个,而是在TabItem中使用了ListView,然后使用以下代码访问它:

<TabControl Name="Tc">
    <TabItem><ListView ItemsSource="{Binding Books}"/></TabItem>
    ...
</TabControl>

<TextBlock Text="{Binding ElementName=Tc, Path=SelectedItem.Content.Items.Count}"/>

这样,每次用户选择不同的Tab时,我的TextBlock的内容都会发生变化 P.S。然而,如果不对这两个答案进行评估,我就不会这样做。

2 个答案:

答案 0 :(得分:1)

在WPF中,我们通常使用数据元素而不是UI元素。通过这种方式,我的意思是通常将数据绑定到我们的代码后面或将视图模型绑定到视图中的UI元素UserControlWindow s。

因此,如果您的代码隐藏或视图模型中有一个名为Books的数据集合属性,那么您可以简单地引用该集合来查找其中有多少项,而不是试图找到它通过UI控件:

<ListView ItemsSource="{Binding Books}" />

您甚至可以将项目计数作为单独的属性公开,并且数据直接绑定到它:

public ObservableCollection<Book> Books
{
    get { return books; }
    set 
    { 
        books = value; 
        NotifyPropertyChanged("Books"); 
        NotifyPropertyChanged("BookCount");
    }
}

public int BookCount
{
    get { return Books.Count; }
}

更新&gt;&gt;&gt;

在回复您的最新评论时,您可以了解如何从MSDN上的How to: Find ControlTemplate-Generated Elements页面ControlTemplate内访问UI元素。简而言之,您需要访问已应用ControlTemplate的元素(在您的情况下为相关的TabItem),然后您可以使用FrameworkTemplate.FindName Method来查找内部声明的元素。从链接页面中获取此示例:

// Finding the grid that is generated by the ControlTemplate of the Button
Grid gridInTemplate = (Grid)myButton1.Template.FindName("grid", myButton1);

// Do something to the ControlTemplate-generated grid
MessageBox.Show("The actual width of the grid in the ControlTemplate: "
    + gridInTemplate.GetValue(Grid.ActualWidthProperty).ToString());

答案 1 :(得分:1)

如果您为所有实体都有单独的集合类,则可以使用以下方法

定义集合类的数据模板

例如

<DataTemplate DataType="{x:Type l:BookCollection}">
    <ListView ItemsSource="{Binding}" />
</DataTemplate>

XAML

<TabControl x:Name="Tc">
    <TabItem Header="Books"
             Content="{Binding Books}" />
    <TabItem Header="DVD's"
             Content="{Binding DVDs}" />
</TabControl>

或者如果您没有单独的集合,则按如下方式使用DataTemplate

<TabControl  x:Name="Tc">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <ListView ItemsSource="{Binding}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabItem Header="Books"
             Content="{Binding Books}" />
    <TabItem Header="DVD's"
             Content="{Binding DVDs}" />
</TabControl>

然后用于获取所选标签项目计数的绑定将是

<TextBlock Text="{Binding SelectedItem.Content.Count, ElementName=Tc}" />