WPF嵌套ItemsControl中x:Reference无法找到内部控件问题求助
嵌套ItemsControl中x:Reference找不到元素的问题分析与解决
你遇到的这个问题,本质是WPF中DataTemplate的可视化树隔离特性在搞事情。
咱们先理清楚为啥外层能用、内层不行:外层的ModuleFunStateInRackRoot是直接放在主可视化树里的,不属于任何模板,所以你用x:Reference指向它的时候,解析器能直接找到这个元素。但内层的ModuleFunStateRoot是定义在ItemTemplate里面的——模板本身只是一个“蓝图”,它不会直接成为可视化树的一部分,只有当ItemsControl加载数据项时,才会为每个项实例化一份模板内容。在模板定义阶段,根本不存在名为ModuleFunStateRoot的实际元素实例,自然就会报错找不到它。
下面给你两种靠谱的解决方法:
方法一:改用RelativeSource传递父级ItemsControl(推荐)
放弃用x:Reference传ItemsSource,改成在绑定里通过RelativeSource找到当前项所属的内层ItemsControl,把它作为参数传给转换器。这样既避开了模板隔离的问题,也不用让转换器继承FrameworkContentElement,代码更简洁。
修改XAML代码
<ItemsControl ItemsSource="{Binding ModuleFunState}" x:Name="ModuleFunStateRoot"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <Label Content="Module Functional State Id: "/> <TextBlock VerticalAlignment="Center"> <TextBlock.Text> <!-- 绑定当前数据项,同时把父级ItemsControl作为转换器参数传入 --> <Binding Converter="{StaticResource ItemIndexConverter}" ConverterParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" /> </TextBlock.Text> </TextBlock> </StackPanel> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
修改转换器代码
去掉FrameworkContentElement继承,直接从参数里拿到ItemsControl,再获取它的ItemsSource计算索引:
[ValueConversion(typeof(object), typeof(int))] public sealed class ItemIndexConverter : IValueConverter { public object Convert(object dataItem, Type targetType, object parameter, CultureInfo culture) { // 从参数里拿到当前的ItemsControl if (parameter is ItemsControl parentItemsControl) { var itemsSource = parentItemsControl.ItemsSource as IList; // 返回索引,找不到就返回-1 return itemsSource?.IndexOf(dataItem) ?? -1; } return -1; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
方法二:利用ItemsControl的AlternationIndex属性(无需转换器)
如果你的需求只是给项显示连续的序号(从0或1开始),可以直接用WPF内置的AlternationIndex特性,不用写转换器:
<ItemsControl ItemsSource="{Binding ModuleFunState}" x:Name="ModuleFunStateRoot" AlternationCount="1000"> <!-- 设置一个比你的最大项数大的值 --> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <Label Content="Module Functional State Id: "/> <!-- 绑定父级ItemsControl的AlternationIndex,默认从0开始 --> <TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=(ItemsControl.AlternationIndex)}" /> <!-- 如果要从1开始,可以用MultiBinding加1,或者写个简单的转换器 --> </StackPanel> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
内容的提问来源于stack exchange,提问作者Wojciech Szabowicz
相关产品推荐
相关产品推荐

