如何将正确的上下文传递给 WPF ListView 的 ItemTemplate 中的 DataTemplate

问题描述

在我的 WPF 应用程序中有一个 ListView 定义如下:

            <ListView
            HorizontalContentAlignment="Stretch"
            DockPanel.Dock="Top"
            Grid.IsSharedSizeScope="True"
            ItemsSource="{Binding Path=ListSource}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid HorizontalAlignment="Stretch">
                        <Grid.ColumnDeFinitions>
                            <ColumnDeFinition Width="Auto" SharedSizeGroup="ParameterIconSize" />
                            <ColumnDeFinition
                                Width="Auto"
                                MaxWidth="100"
                                SharedSizeGroup="ParameterDescriptionSize" />
                            <ColumnDeFinition
                                Width="Auto"
                                MinWidth="40"
                                SharedSizeGroup="ParameterValueSize" />
                        </Grid.ColumnDeFinitions>
                        <Image
                            Grid.Column="0"
                            MaxHeight="50"
                            Source="{Binding Path=Icon}" />
                        <ContentPresenter
                            Grid.Column="2"
                            Content="{Binding Path=RenderValue,Converter={StaticResource RenderObjTovalueConverter}}"
                            ContentTemplateSelector="{StaticResource ResourceKey=RenderTemplateSelector}"
                            />
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

我已将 Resources 中的所有内容定义如下:

            <!--  TEXT  -->
        <DataTemplate x:Key="TextValueTemplate">
            <DockPanel DataContext="{StaticResource VM}">
                <TextBlock
                    MaxWidth="75"
                    Margin="5,0"
                    VerticalAlignment="Center"
                    Background="Red"
                    DockPanel.Dock="Top"
                    FontSize="14"
                    Text="{Binding Path=Description,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
                    TextTrimming="CharacterEllipsis">
                    <TextBlock.ToolTip>
                        <TextBlock
                            MaxWidth="100"
                            Text="{Binding Path=Description,UpdateSourceTrigger=PropertyChanged}"
                            textwrapping="Wrap" />
                    </TextBlock.ToolTip>
                </TextBlock>
              </DockPanel>
        </DataTemplate>

        <!--  IMAGE  -->
        <DataTemplate x:Key="ImageValueTemplate">
            <DockPanel DataContext="{StaticResource VM}">
                <Image MaxHeight="50" Source="{Binding Path=CurrentValueImage}" />               
            </DockPanel>
        </DataTemplate>

        <!--  COMBO Box  -->
        <DataTemplate x:Key="CombovalueTemplate">
            <DockPanel DataContext="{StaticResource VM}">
                <TextBlock
                    Grid.Column="1"
                    MaxWidth="75"
                    Margin="5,0"
                    VerticalAlignment="Center"
                    FontSize="14"
                    Text="{Binding Path=Description,UpdateSourceTrigger=PropertyChanged}"
                            textwrapping="Wrap" />
                    </TextBlock.ToolTip>
                </TextBlock>
                <ComboBox/>
                
            </DockPanel>
        </DataTemplate>

        <sel:ParameterVisualizationTemplateSelector
            x:Key="RenderTemplateSelector"
            ComboTemplate="{StaticResource ResourceKey=CombovalueTemplate}"
            GraphicTemplate="{StaticResource ResourceKey=ImageValueTemplate}"
            TextTemplate="{StaticResource ResourceKey=TextValueTemplate}" />

一切都编译并运行,但我无法正确地将 ListViewItem 传递给内部数据模板。

我想要做的是能够根据图像、一些文本和组合框之间的某些逻辑(此处未显示)更改显示内容。这些控件中的内容ListViewItem 中定义。如您所见,我尝试编写一个返回相应类型(图像、文本、数据列表)的转换器,但我缺少各种 DataTemplates间的链接

最终编辑:根据@mm8 的回答,我发现真正的问题不是传递上下文,而是传递的属性没有得到正确处理,然后不会设置任何值,同时不会给出任何绑定错误

解决方法

当您在模板中设置 DataContext="{StaticResource VM}" 时,您实际上是在“覆盖”默认 DataContext,它是 ListSourceListView 源集合中的当前项目。

所以,如果我理解正确的话,“依赖”链就像控件

您将 ItemsSourceListView 绑定到名为 ListSource 的源集合属性:

 <ListView ... ItemsSource="{Binding Path=ListSource}">

DataContextGrid 中根元素(在本例中为 ListView)的默认 ItemTemplate 将是 ListSource 中的元素.

这意味着如果 ListSource 返回 IEnumerable<T>,您可以直接绑定到 TItemTemplate 类型的任何公共属性,前提是您没有显式设置模板中某处的 DataContext 属性。

因此,在您的示例中,Icon 应该是 T 的属性(无论您的类型 T 是什么):

<Image Grid.Column="0"
       MaxHeight="50"
       Source="{Binding Path=Icon}" />

例如,如果您从 DataContext="{StaticResource VM}" 中删除 TextValueTemplate,只要在从转换器返回的对象中定义了 Description 属性,则对 Description 的绑定应该可以工作RenderValue 属性。