WPF Listbox 控件模板不显示 Listboxitem 控件模板和 ItemTemplate 数据模板

Posted

技术标签:

【中文标题】WPF Listbox 控件模板不显示 Listboxitem 控件模板和 ItemTemplate 数据模板【英文标题】:WPF Listbox control template not showing Listboxitem control template and ItemTemplate data template 【发布时间】:2020-05-12 11:46:08 【问题描述】:

当我在我的 ListBox 控件模板中使用 ItemsControl 时,我的 ListBoxItem 控件模板没有应用。

我有一个自定义 ListBox 控件模板以及一个包裹在样式中的 ListBoxItem 控件模板。在我的主窗口中,我有一个带有数据模板的 ListBox 声明。

控制模板:

<Style TargetType="ListBoxItem" BasedOn="StaticResource Base_Control_Style">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="x:Type ListBoxItem">
                <Border x:Name="border" BorderThickness="0" 
                        BorderBrush="Transparent" Background="Transparent">
                    <ContentPresenter Content="TemplateBinding Content" Margin="2"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="border" Property="Background" 
                                Value="StaticResource Base_PrimaryLight"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter TargetName="border" Property="Background" 
                                Value="StaticResource Base_Secondary"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsSelected" Value="True"/>
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter TargetName="border" Property="Background"
                                    Value="StaticResource Base_SecondaryDark"/>
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style TargetType="ListBox" BasedOn="StaticResource Base_Control_Style">
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Background" Value="StaticResource Base_PrimaryDark"/>

    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBox">
                <Border x:Name="Border" BorderThickness="TemplateBinding BorderThickness" 
                        BorderBrush="TemplateBinding BorderBrush" Background="TemplateBinding Background">
                    <ScrollViewer Margin="2">
                        <!--<StackPanel IsItemsHost="true"/>-->
                        <!--<ItemsPresenter/>-->
                        <ItemsControl ItemsSource="TemplateBinding ItemsSource" 
                                      ItemTemplate="TemplateBinding ItemTemplate"/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

列表框声明:

<ListBox x:Name="recipients_listbox" Margin="10" ItemsSource="Binding Path=Recipients" 
                 SelectedValuePath="Email"
                 SnapsToDevicePixels="True"
                 HorizontalContentAlignment="Stretch" ScrollViewer.CanContentScroll="False">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="2,4" HorizontalAlignment="Stretch" >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="60"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>

                        <Grid.Resources>
                            <Style TargetType="TextBlock">
                                <Setter Property="Foreground" Value="Black"/>
                            </Style>
                        </Grid.Resources>

                        <Image Source="Binding ImagePath" 
                               RenderOptions.BitmapScalingMode="HighQuality" 
                               SnapsToDevicePixels="True"
                               Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" 
                               Stretch="UniformToFill" Margin="0,0,10,0"/>

                        <TextBlock Text="Name:" FontWeight="Bold" 
                                   Grid.Column="1" Grid.Row="0" VerticalAlignment="Center"/>
                        <TextBlock Text="Email:" FontWeight="Bold" 
                                   Grid.Column="1" Grid.Row="1" VerticalAlignment="Center"/>
                        <TextBlock Text="Department:" FontWeight="Bold" 
                                   Grid.Column="1" Grid.Row="2" VerticalAlignment="Center"/>

                        <TextBlock VerticalAlignment="Center" Grid.Column="3" Grid.Row="0">
                                    <Run Text="Binding FirstName"/>
                                    <Run Text="Binding LastName"/>
                        </TextBlock>
                        <TextBlock Text="Binding Email" 
                                   VerticalAlignment="Center" Grid.Column="3" Grid.Row="1"/>
                        <TextBlock Text="Binding Department" 
                                   VerticalAlignment="Center" Grid.Column="3" Grid.Row="2"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

问题是当我在我的 ListBox 控件模板中使用 ItemsControl 时,我的 ListBoxItem 控件模板没有应用(更改背景颜色的触发器不会激活),而我的数据模板是。

带有 ItemsControl 的列表框

我尝试使用带有 isItemsHost=True 的 StackPanel 以及 ItemsPresenter。这两个选项都应用了我的 ListBoxItem 控件模板,但没有应用我的数据模板。

带有 StackPanel 或 ItemsPresenter 的列表框

有什么方法可以同时应用我的 ListBoxItem 控件模板和数据模板?

【问题讨论】:

在 ListBox 的 ControlTemplate 中有一个 ItemsControl 是没有意义的。应该有一个 StackPanel 或一个 ItemsPresenter。见这里:docs.microsoft.com/en-us/dotnet/framework/wpf/controls/… 没有应用我的数据模板”到底是什么意思?项目模板? 当我有一个 ItemsPresenter 或 StackPanel 而不是 ItemsControl 时,我在第二个代码 sn-p 中定义的 ItemTemplate 不适用。 【参考方案1】:

ListBoxItem 样式中 ControlTemplate 中的 ContentPresenter 不使用 ContentTemplate 属性,该属性包含 ListBox 的 ItemTemplate 属性的 DataTemplate。

添加适当的 TemplateBinding:

<Style TargetType="ListBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Border ...>
                    <ContentPresenter Content="TemplateBinding Content"
                                      ContentTemplate="TemplateBinding ContentTemplate"
                                      Margin="2"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    ...
</Style>

然后要么在 ListBox 的 ControlTemplate 中使用 ItemsPresenter,要么根本不设置 Template 属性:

<Style TargetType="ListBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBox">
                <Border BorderThickness="TemplateBinding BorderThickness" 
                        BorderBrush="TemplateBinding BorderBrush"
                        Background="TemplateBinding Background">
                    <ScrollViewer Margin="2">
                        <ItemsPresenter/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    ...
</Style>

【讨论】:

以上是关于WPF Listbox 控件模板不显示 Listboxitem 控件模板和 ItemTemplate 数据模板的主要内容,如果未能解决你的问题,请参考以下文章

WPF 自定义列表筛选 自定义TreeView模板 自定义ListBox模板

〝WPF〞中的〝ListBox〞、〝ListView〞和〝DataGridView〞有啥区别?

WPF中的ListBox,ListView和DataGridView有啥区别

将 WPF 控件设置为扩展以填充可用空间,仅此而已

WPF 数据模板

wpf listbox 显示不全 而且没滚动条