为ListBox项模板应用现有样式

时间:2013-12-12 11:42:13

标签: wpf listbox styles wpf-controls listboxitem

我正在尝试为ListBox中的项目添加样式,我之前为ListViewItem创建了这种样式,它关于TextBlock,Image和Border,当项目事件引发时它会改变颜色( IsSelected ,IsMouseOver,IsSelectionActive ),现在我想保留这种风格并将其应用于添加到ListBox的任何项目

    <Style x:Key="ListBoxPCInfoStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Padding" Value="2,0,0,0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
                        <Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding  RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
                        <Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
                        <TextBlock HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{TemplateBinding Name}" VerticalAlignment="Bottom" Width="Auto" Height="17" TextAlignment="Center" Margin="4,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" TargetName="border">
                                <Setter.Value>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="#33C1DEFF" Offset="0"/>
                                        <GradientStop Color="#41A5CDFF" Offset="1"/>
                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                            <Setter Property="BorderBrush" TargetName="border" Value="#FF7DA2CE"/>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="BorderBrush" TargetName="border" Value="#FF7DA2CE"/>
                            <Setter Property="Background" TargetName="border">
                                <Setter.Value>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="#97C1DEFF" Offset="0"/>
                                        <GradientStop Color="#A7A5CDFF" Offset="1"/>
                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="Selector.IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="BorderBrush" TargetName="border" Value="#FFB4B4B4"/>
                            <Setter Property="Background" TargetName="border">
                                <Setter.Value>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="#7FE5E5E5" Offset="0"/>
                                        <GradientStop Color="#B2CCCCCC" Offset="1"/>
                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

我有这个ListBox

<ListBox x:Name="ListHosts" Background="{x:Null}" BorderBrush="{x:Null}">
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="50" CornerRadius="2.5"/>
                    <Image x:Name="Img" Source="BtnImg/Computer.png" Stretch="None" Margin="3,0,10,0"/>
                    <TextBlock x:Name="PCName" Margin="0,7" TextWrapping="Wrap" Height="16" HorizontalAlignment="Left"><Run Text="{Binding Name}"/></TextBlock>
                </StackPanel>

            </DataTemplate>
        </ListBox>

我觉得我在这里缺少一些简单的东西......有人能帮助我发现它吗?

1 个答案:

答案 0 :(得分:0)

2个选项:

从样式中删除x:Key

 <Style TargetType="{x:Type ListBoxItem}">
    <!-- ... -->

这将使样式适用于资源范围内的所有 ListBoxItem

明确引用ListBox中的样式:

<ListBox ItemContainerStyle="{StaticResource ListBoxPCInfoStyle}">
    <!-- ... -->

----------------------------------------------- --------------------------------------------

无论如何,你所有的XAML都错了。您正在定义ListBoxItem.Template,如下所示:

                <Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
                    <Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding  RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
                    <Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
                    <TextBlock HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{TemplateBinding Name}" VerticalAlignment="Bottom" Width="Auto" Height="17" TextAlignment="Center" Margin="4,0"/>
                </Grid>

这使得自定义DataTemplates无法在任何地方引入。您需要在某处留下ContentPresenter,以便WPF有机会将DataTemplated内容放在其中。

TextBlock毫无意义。你绑定了ListBoxItem.Name属性,这是完全无关紧要的,没有任何意义可以显示在用户界面中,无论如何都无法控制。

数据不属于ControlTemplate s,仅属于DataTemplate s。

更改模板,如下所示:

                <Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
                    <Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding  RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
                    <Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
                    <ContentPresenter ContentSource="Content"/> 
                </Grid>

ListBox XAML也错了:

通过这样做:

<ListBox ...>
  <DataTemplate>
      <!-- ... -->
  </DataTemplate>
</ListBox>

您将DataTemplate作为项目放在ListBox中,这不是您想要的。 您需要专门为DataTemplate指定ItemTemplate作为ListBox

<ListBox ...>
   <ListBox.ItemTemplate>
      <DataTemplate>
          <!-- ... -->
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

为什么Image.Source绑定到double类型的属性?这是没有意义的。 要么在那里放一个特定的资源:

<Image Source="/resources/somepic.png"/>

如果您想动态更改依赖于某些数据的图片,那么该图片属于DataTemplate,而不属于ControlTemplate

----------------------------------------------- --------------------------------------------

我建议你阅读以下资料: