积极答复者
[关于GridView模版]如何通过ItemContainerGenerator获取ItemTemplate中的控件

问题
-
在使用Gridview中遇到个问题,希望哪位大侠帮忙看看。
//GridView如下
<GridView x:Name="GridView5" IsSwipeEnabled="False" Visibility="Visible" ItemsSource="{Binding Source={StaticResource cvs2}}" ItemTemplate="{StaticResource myTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollMode="Enabled" SelectionMode="None" Loaded="GridView5_Loaded_1"> <GridView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel Orientation="Vertical" HorizontalAlignment="Center"/> </ItemsPanelTemplate> </GridView.ItemsPanel> </GridView>
//数据模版如下
<DataTemplate x:Key="myTemplate"> <Grid> <Path x:Name="TextSelectionShape" Opacity="0.33" Visibility="Visible" Fill="OrangeRed"></Path> <Grid Background="Transparent"> <Image Source="{Binding wbmp}" Width="{Binding PageWidth}" Height="{Binding PageHeight}"/> </Grid> </Grid> </DataTemplate>
//通过遍历可视树获取子控件
GridViewItem^ __gvi = safe_cast<GridViewItem^>(GridView5->ItemContainerGenerator->ContainerFromIndex(Index)); Path^ __Path = GetVisualChild_Path( __gvi,L"TextSelectionShape");
请问为什么我总是获取不到想要的Path控件呢?//遍历可视树方法
Windows::UI::Xaml::Shapes::Path^ GetVisualChild_Path(Windows::UI::Xaml::DependencyObject ^parent,String^ name) { Path^ child = nullptr; int numVisuals = VisualTreeHelper::GetChildrenCount(parent); for(int i=0;i<numVisuals;i++){ DependencyObject ^d = (DependencyObject^) VisualTreeHelper::GetChild(parent,i); child = dynamic_cast<Path^>(d); if(child == nullptr || child->Name!=name) child = GetVisualChild_Path(d,name); else break; } return child; }
答案
-
嘿嘿,本来想偷个小懒的,看来不行,我仔细看了下你的可视树遍历的代码。在找到真正想要的Path后你没有阻断循环,还在继续循环遍历,所以出来的结果永远是null。
正确的方法应该是:
Windows::UI::Xaml::Shapes::Path^ GetVisualChild_Path(Windows::UI::Xaml::DependencyObject ^parent,String^ name) { Path^ child = nullptr; int numVisuals = VisualTreeHelper::GetChildrenCount(parent); for(int i=0;i<numVisuals;i++){ DependencyObject ^d = (DependencyObject^) VisualTreeHelper::GetChild(parent,i); child = dynamic_cast<Path^>(d); if(child == nullptr || child->Name!=name) { child = GetVisualChild_Path(d,name); if (child != nullptr) return child; } else return child; } return nullptr; }
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已建议为答案 Jie BaoModerator 2012年6月13日 2:39
- 已标记为答案 frglig 2012年6月14日 2:03
全部回复
-
还是可能虚拟化导致你要获得的那个 ItemContainer还没有生成,所以 这一行 GridViewItem^ __gvi = safe_cast<GridViewItem^>(GridView5->ItemContainerGenerator->ContainerFromIndex(Index)); 其实返回了一个NULL的__gvi。
VirtualizingStackPanel 这个ItemsPanel 是支持虚拟化的,能够根据显示的需要去动态生成ItemContainer。
你用是StackPanel试试看。
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已编辑 Jie BaoModerator 2012年6月12日 3:02
-
谢谢Bob的回复。
可以确定这不是虚拟化的问题:
1.调试过程中,__gvi的值不是NULL。
2.我是在控件完全加载完之后,响应鼠标的操作来获取Container的。
经过调试,发现遍历可视化子树得到的子控件,都是ItemContainerStyle中的,如“<Path x:Name="SelectingGlyph" .../>”,
而ItemTemplate中的控件并不能被遍历到。
我的ItemContainerStyle是用默认的,可以从blend里获得。
PS:按照您的建议把VirualizingStackPanel 换成StackPanel,结果并未有任何改变,还是无法获取到ItemTemplate中的控件。
关于那个Flipview的虚拟化的问题,我已经知道了,所以这个问题应该另有来源吧?
附上flipview问题的链接给需要的人参考:
-
嘿嘿,本来想偷个小懒的,看来不行,我仔细看了下你的可视树遍历的代码。在找到真正想要的Path后你没有阻断循环,还在继续循环遍历,所以出来的结果永远是null。
正确的方法应该是:
Windows::UI::Xaml::Shapes::Path^ GetVisualChild_Path(Windows::UI::Xaml::DependencyObject ^parent,String^ name) { Path^ child = nullptr; int numVisuals = VisualTreeHelper::GetChildrenCount(parent); for(int i=0;i<numVisuals;i++){ DependencyObject ^d = (DependencyObject^) VisualTreeHelper::GetChild(parent,i); child = dynamic_cast<Path^>(d); if(child == nullptr || child->Name!=name) { child = GetVisualChild_Path(d,name); if (child != nullptr) return child; } else return child; } return nullptr; }
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
- 已建议为答案 Jie BaoModerator 2012年6月13日 2:39
- 已标记为答案 frglig 2012年6月14日 2:03