首页 > 解决方案 > 如何将正确的上下文传递给 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, Mode=OneWay, 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, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                    TextTrimming="CharacterEllipsis">
                    <TextBlock.ToolTip>
                        <TextBlock
                            MaxWidth="100"
                            Text="{Binding Path=Description, Mode=OneWay, 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 的回答,我发现真正的问题不是传递上下文,而是传递的属性没有被正确处理,然后在没有给出任何绑定错误的情况下不会设置任何值。

标签: wpfxamlbindingdatatemplate

解决方案


当您DataContext="{StaticResource VM}"在模板中设置时,您实际上DataContext是在“覆盖”默认值,ListSourceListView.

所以,如果我理解正确的话,“依赖”链类似于控制<- textItemtemplate <- ListViewItemTemplate <- Viewmodel,所以最终控制会自动“继承”对象?

您将 的 绑定ItemsSourceListView一个名为的源集合属性ListSource

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

'sDataContext中的根元素(Grid在本例中为 )的默认值将是.ListViewItemTemplateListSource

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

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

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

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


推荐阅读