问题描述
我在尝试查找在 DataTemplate 中声明的元素时遇到问题,该元素之后像 ContentTemplate 一样应用于 TabItem 对象.我看到已经有一些关于这个问题的解决方案,但没有一个真正适用于我的情况,我想了解原因(显然我在某些地方犯了错误)这是一个示例代码:
I got a problem trying to find an element declared in DataTemplate, that after was applied like a ContentTemplate to TabItem object.I saw that there is already some solutions in regard of this problem, but no one of them actually works in my case, and I would like to understand why (obviously I make mistake in some place)Here is a sample code:
<DataTemplate x:Key="TabItemDataTemplate">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Name="templateGrid">
<Grid.RowDefinitions>
<RowDefinition Height="6.0*"> </RowDefinition>
<RowDefinition Height="6" ></RowDefinition>
<RowDefinition Height="6.0*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<ListView x:Name="repoView" Grid.Row="0"
VerticalAlignment="Stretch"
ItemsSource="{Binding Source={StaticResource DataProviderForListView}}">
<GridView>
<GridViewColumn Header="State"
DisplayMemberBinding="{Binding Path=RepositoryItemState}"/>
<GridViewColumn Header="Working Copy Rev num."
DisplayMemberBinding="{Binding Path=WCRevision}"/>
<GridViewColumn Header="Repository Rev num."
DisplayMemberBinding="{Binding Path=RepoRevision}"/>
<GridViewColumn Header="User"
DisplayMemberBinding="{Binding Path=Account}"/>
<GridViewColumn Header="Item"
DisplayMemberBinding="{Binding Path=ItemName}"/>
</GridView>
</ListView>
<GridSplitter x:Name="gridSplitter" Grid.Row="1"
ResizeDirection="Rows" Background="Gray"
Height="4" HorizontalAlignment="Stretch"
Style="{StaticResource gridSplitterStyle}"/>
<RichTextBox x:Name="rowView" Grid.Row="2"
BorderBrush="Bisque" VerticalAlignment="Stretch"
IsReadOnly="True" Background="YellowGreen"
FontFamily="Comic Sans Serif"/>
<ToggleButton x:Name="rbWorkingCopy"
Template="{StaticResource ToggleButtonControlTemplate}"
Grid.Row="3" Width="100" Height="22"
Content="{StaticResource WorkingCopyTitle}"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Command="repoManager:AppCommands.GetWorkingCopyInfoCommand" />
<ToggleButton x:Name="rbRepository"
Template="{StaticResource ToggleButtonControlTemplate}"
Grid.Row="3" Width="100" Height="22"
Content="{StaticResource RepositoryTitle}"
HorizontalAlignment="Left"
VerticalAlignment="Bottom" Margin="120,0,0,0"
Command="repoManager:AppCommands.GetRepoInfoCommand" />
<ProgressBar x:Name="checkRepositoryProgress" Grid.Row="3"
Width="220" Height="22" HorizontalAlignment="Right"
VerticalAlignment="Bottom" Margin="250,0,10,0"
IsIndeterminate="True"
IsEnabled="{Binding repoManager:ExecutingCommand}" />
</Grid>
</DataTemplate>
此代码通过以下方式以编程方式应用于给定的 TabItem 对象:
This code is porgrammatically applied to the given TabItem object in following way :
this.ContentTemplate = FindResource("TabItemDataTemplate") as DataTemplate;
在我需要访问在 DataTemplate 中声明的 ListView 元素之后,我执行了在 Internet 上以及在此站点上找到的代码.这是一个简短的例子:
After I need access to the ListView element declared in DataTemplate, so I execute the codes found around in internet, and also on this site. Here is a short example:
/* Getting the ContentPresenter of myListBoxItem*/
ContentPresenter myContentPresenter =
FindVisualChild<ContentPresenter>(this);
// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
ListView repoListView = (ListView)myDataTemplate.FindName("repoView",
myContentPresenter);
问题 1:此时 ContentPresenter 的 ContentTemplate 为 Null,因此代码执行崩溃.Prolem2:好的,我想,可能是我需要直接导航 throw TabItem 内容,所以代码或多或少变成了:
Problem1: In this case ContentTemplate of ContentPresenter is Null, so code execution crashes.Prolem2: Ok, I think, may be I need to navigate throw TabItem content directly, so the code becomes, more or less:
/* Getting the ContentPresenter of myListBoxItem*/
ContentPresenter myContentPresenter =
FindVisualChild<ContentPresenter>(this);
// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = this.ContentTemplate;
ListView repoListView = (ListView)myDataTemplate.FindName("repoView",
myContentPresenter);
this 是 TabItem 对象.但奇怪的是,this 的 ContentTemplate 与上面分配的完全不同.我确定我在某个地方遗漏了一些东西,你能帮我找出问题所在吗?谢谢.
this is TabItem object. But the strage things, that the ContentTemplate of this is completely different from that one assigned above. I'm sure that I missed something somewhere, can you help me to figure out the problem ?Thank you.
推荐答案
好的,我们来了 :)我以不是很好的方式解决了这个问题,但似乎可以正常工作.正如我上面提到的,我使用了 LoadContent 方法,它返回了 ListView 对象,但顺便说一下,它不是 UI 实际使用的 ListView.因此,为了解决这个问题,我添加了静态属性来保存我的 REAL ListView 对象(静态的,因为我有单个 DataTemplate,其中包含跨多个 TabItem 共享的 ListView,所以 ListView 也共享)并将事件处理程序添加到我的 DataTemplate -> Loaded强>.捕获此事件,在我的情况下,仅在应用程序的生命周期中引发事件,在 RoutedEvent's OriginalSource 中,我得到了 WPF 引擎用于在 UI 上呈现的 REAL ListView 对象.希望我的解决方案对某人有所帮助.谢谢大家.
Ok, here we come :)I resolve the problem, in not very nice way, but it seems that works correctly.As I mentioned above I used LoadContent method and it returns me the ListView object, but by the way it wasn't the ListView that UI actually uses. So to resolve that problem I add static property to hold my REAL ListView object (static as I have single DataTemplate that contains ListView shared across multiple TabItems, so the ListView shared too) and add event handler to my DataTemplate -> Loaded. Catching this event, that in my case raises only ones in lifetime of application, in RoutedEvent's OriginalSource I got the REAL ListView object that WPF engine uses for rendering on UI.Hope my solution will help someone.Thank you all.
这篇关于在应用于 TabItem 的 DataTemplate 中查找元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!