UWP如何将ListViewItem的可见性绑定到分组数据上下文?
我将分组CollectionViewSource绑定到ListView,组头模板包含折叠分组的按钮,同时分组内的每个项也支持单独折叠。原本希望把ListViewItem的Visibility绑定到组头数据上下文的Expanded属性,但尝试通过ElementName绑定组头中的Grid未生效(推测是多实例重名导致);试过将Expanded值向下传递到子项列表,但因为项需要单独折叠,这个方案不可行;尝试RelativeSource绑定也没成功。目前已经通过修改对象结构解决问题,但想知道最初的思路是否可行。
最初的思路完全可行,问题出在绑定方式的选择上
为什么ElementName绑定失效
每个组头模板实例化后都会生成一个名为GroupGrid的控件,但ListViewItem和组头控件属于不同的命名范围,ElementName绑定只能在当前命名范围内查找控件,所以无法跨范围找到对应的组头Grid,绑定自然失效。
正确的绑定方案:通过RelativeSource访问组容器
ListView的分组项会被包裹在ListViewGroupItem(UWP)或GroupItem(WPF)容器中,这个容器的DataContext是CollectionViewGroup对象:
CollectionViewGroup.Name:对应组头的数据源实例(也就是你的InventoryHistorySectionModel)CollectionViewGroup.Items:对应组内的所有子项
利用这个特性,我们可以通过RelativeSource找到父级的组容器,直接绑定组头模型的Expanded属性:
UWP 实现代码
<ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <!-- 其他Setter配置 --> <Setter Property="Visibility" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Parent.DataContext.Name.Expanded, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/> </Style> </ListView.ItemContainerStyle>
说明:TemplatedParent指向当前ListViewItem,它的Parent是ListViewGroupItem,后者的DataContext是CollectionViewGroup,通过Name就能拿到组头的InventoryHistorySectionModel实例,直接访问Expanded属性即可。
WPF 实现代码
<ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <!-- 其他Setter配置 --> <Setter Property="Visibility" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type GroupItem}}, Path=DataContext.Name.Expanded, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/> </Style> </ListView.ItemContainerStyle>
说明:直接通过AncestorType查找父级的GroupItem,它的DataContext是CollectionViewGroup,同样通过Name访问组头模型的Expanded属性。
与项单独折叠的兼容性
这个绑定方式仅控制组级别的显示/隐藏:
- 当组的
Expanded为false时,所有子项都会隐藏 - 当组的
Expanded为true时,子项可以根据自身的Expanded属性单独控制显示(在ItemTemplate的根控件上绑定自身的Expanded即可),完全满足你“组折叠+项单独折叠”的需求。
内容的提问来源于stack exchange,提问作者JayF

