WPF. ListBox 项目样式

4

我有一个关于ListBox项目样式的问题,我创建了两种样式,但不知道如何同时使用它们。第一种样式用于ListBox项目大小、鼠标悬停颜色等,第二种样式用于项目背景(Alternation count)。如果我只留下其中一个,它们工作正常,但如何使它们同时工作呢?或者我能否将它们写成一个样式?

我的代码是:

..... <Style x:Key="Style2"
       TargetType="{x:Type ListBoxItem}">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border 
                        Name="Border"
                        Padding="7"
                        SnapsToDevicePixels="True">
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter TargetName="Border" Property="Background"
                                    Value="{StaticResource SelectedBackgroundBrush}"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground"
                                    Value="{StaticResource DisabledForegroundBrush}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                <Setter Property="Background" Value="#FFFFFF"></Setter>
            </Trigger>
            <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                <Setter Property="Background" Value="#F7F7F7"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style  x:Key="{x:Type ListBoxItem}"
        TargetType="{x:Type ListBoxItem}"
        BasedOn="{StaticResource Style2}">
        <Style.Triggers>
            <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                <Setter Property="Background" Value="#19f39611"></Setter>
            </Trigger>
            <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                <Setter Property="Background" Value="#19000000"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>


<Grid >
    <ScrollViewer Margin="30,98,362,30">
        <ListBox x:Name="lbPersonList" AlternationCount="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </ScrollViewer>
</Grid>

3个回答

7
你可以使用 BasedOn
<Style x:Key="Style1" TargetType="ListBoxItem">
    ...
</Style>

<Style x:Key="{x:Type ListBoxItem}" TargetType="ListBoxItem" BasedOn={StaticResource Style1}>
    ...
</Style>

问题出在ControlTemplate的Background设置器上。这是解决方案(使用AlternationConverter而不是触发器):

<Window.Resources>
    <AlternationConverter x:Key="BackgroundConverter">
        <SolidColorBrush Color="#19f39611" />
        <SolidColorBrush Color="#19000000" />
    </AlternationConverter>

    <Style x:Key="Style2" TargetType="{x:Type ListBoxItem}">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Name="Border" Padding="7" SnapsToDevicePixels="True" Background="{TemplateBinding Background}">
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter TargetName="Border" Property="Background" Value="Gray"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="Green"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="Style1" TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource Style2}">
        <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self},
                 Path=(ItemsControl.AlternationIndex),
                 Converter={StaticResource BackgroundConverter}}"/>
    </Style>
</Window.Resources>

<ListBox x:Name="lbPersonList" AlternationCount="2" ItemContainerStyle="{StaticResource Style1}">
...

如果我使用你的示例,我该如何在ListBox选项中调用这种样式?因为现在它只能工作在style1上(Alternationcount无法工作)。 - LTU
问题出在ControlTemplate的Background设置器上。我编辑了我的回答。 - Nacho

1

使用动态资源,您可以使用单个列表框项样式来实现此目的。

 <Window.Resources>                              
    <Style x:Key="Lststyle" TargetType="ListBoxItem">           
        <Setter Property="SnapsToDevicePixels" Value="true"/>        
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Name="Border" Background="Transparent" Padding="7" SnapsToDevicePixels="True">                         
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="ListBox.AlternationIndex" Value="0">
                            <Setter TargetName="Border"  Property="Background" Value="{DynamicResource Color0}"/>
                        </Trigger>
                        <Trigger Property="ListBox.AlternationIndex" Value="1">
                            <Setter TargetName="Border"  Property="Background" Value="{DynamicResource Color1}"/>
                        </Trigger>
                        <Trigger Property="ListBoxItem.IsSelected" Value="true">
                            <Setter TargetName="Border" Property="Background" Value="Green"/>
                        </Trigger>
                        <Trigger Property="ListBoxItem.IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="LightGray"/>
                        </Trigger>                           
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>          
    </Style>   
</Window.Resources>

<StackPanel >
    <TextBlock Text="Listbox1"></TextBlock>
    <ScrollViewer >
        <ListBox x:Name="lbPersonList" ItemContainerStyle="{StaticResource Lststyle}" AlternationCount="2"> 
            <ListBox.Resources>
                <SolidColorBrush x:Key="Color0" Color="#19f39611"></SolidColorBrush>
                <SolidColorBrush x:Key="Color1" Color="#19000000"></SolidColorBrush>
            </ListBox.Resources>
            <TextBlock Text="listboxitem1"></TextBlock>
            <TextBlock  Text="listboxitem1"></TextBlock>
            <TextBlock Text="listboxitem1"></TextBlock>
        </ListBox>
    </ScrollViewer>
    <TextBlock Margin="0,10,0,0" Text="Listbox2"></TextBlock>
    <ScrollViewer>
        <ListBox x:Name="lbPersonList1" ItemContainerStyle="{StaticResource Lststyle}" AlternationCount="2">
            <ListBox.Resources>
                <SolidColorBrush x:Key="Color0" Color="Yellow"></SolidColorBrush>
                <SolidColorBrush x:Key="Color1" Color="Blue"></SolidColorBrush>
            </ListBox.Resources>
            <TextBlock Text="listboxitem1"></TextBlock>
            <TextBlock Text="listboxitem1"></TextBlock>
            <TextBlock Text="listboxitem1"></TextBlock>
        </ListBox>
    </ScrollViewer>
</StackPanel>

简化的XAML。
<Window.Resources>
    <Style x:Key="lst1" TargetType="ListBox" >
        <Style.Resources>
            <SolidColorBrush x:Key="Color0" Color="#19f39611"></SolidColorBrush>
            <SolidColorBrush x:Key="Color1" Color="#19000000"></SolidColorBrush>
        </Style.Resources>
    </Style>
    <Style x:Key="lst2" TargetType="ListBox" >
        <Style.Resources>
            <SolidColorBrush x:Key="Color0" Color="Blue"></SolidColorBrush>
            <SolidColorBrush x:Key="Color1" Color="Yellow"></SolidColorBrush>
        </Style.Resources>
    </Style>
    <Style x:Key="Lststyle" TargetType="ListBoxItem">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Name="Border" Background="Transparent" Padding="7" SnapsToDevicePixels="True">
                        <Border.Style>
                            <Style TargetType="Border">
                                <Style.Triggers>
                                    <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                                        <Setter  Property="Background" Value="{DynamicResource Color0}"/>
                                    </Trigger>
                                    <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                                        <Setter  Property="Background" Value="{DynamicResource Color1}"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Border.Style>
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="ListBox.AlternationIndex" Value="0">
                            <Setter TargetName="Border"  Property="Background" Value="{DynamicResource Color0}"/>
                        </Trigger>
                        <Trigger Property="ListBox.AlternationIndex" Value="1">
                            <Setter TargetName="Border"  Property="Background" Value="{DynamicResource Color1}"/>
                        </Trigger>
                        <Trigger Property="ListBoxItem.IsSelected" Value="true">
                            <Setter TargetName="Border" Property="Background" Value="Green"/>
                        </Trigger>
                        <Trigger Property="ListBoxItem.IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="LightGray"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>
<StackPanel >
    <TextBlock Text="Listbox1"></TextBlock>
    <ScrollViewer >
        <ListBox x:Name="lbPersonList" Style="{StaticResource lst1}" ItemContainerStyle="{StaticResource Lststyle}" AlternationCount="2">![enter image description here][2]              
            <TextBlock Text="listboxitem1"></TextBlock>
            <TextBlock  Text="listboxitem1"></TextBlock>
            <TextBlock Text="listboxitem1"></TextBlock>
        </ListBox>
    </ScrollViewer>
    <TextBlock Margin="0,10,0,0" Text="Listbox2"></TextBlock>
    <ScrollViewer>
        <ListBox x:Name="lbPersonList1" Style="{StaticResource lst2}" ItemContainerStyle="{StaticResource Lststyle}" AlternationCount="2">               
            <TextBlock Text="listboxitem1"></TextBlock>
            <TextBlock Text="listboxitem1"></TextBlock>
            <TextBlock Text="listboxitem1"></TextBlock>
        </ListBox>
    </ScrollViewer>
</StackPanel>

enter image description here


0
你应该为每个样式设置适当的`x:Key`,然后对于其中一个样式,你可以使用`BasedOn={StaticResource Style1}`将其附加到当前样式中。 (请查看文档:https://msdn.microsoft.com/en-us/library/system.windows.style.basedon(v=vs.110).aspx)
请检查这个。
    <Style x:Key="Style2"
           TargetType="ListBoxItem">
        <Style.Triggers>
            <Trigger Property="ItemsControl.AlternationIndex"
                     Value="0">
                <Setter Property="Background"
                        Value="#19f39611"></Setter>
            </Trigger>
            <Trigger Property="ItemsControl.AlternationIndex"
                     Value="1">
                <Setter Property="Background"
                        Value="#19000000"></Setter>
            </Trigger>
        </Style.Triggers>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Name="Border"
                            Padding="7"
                            SnapsToDevicePixels="True">
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected"
                                 Value="true">
                            <Setter Property="Background"
                                    Value="Red" />
                        </Trigger>
                        <Trigger Property="IsEnabled"
                                 Value="false">
                            <Setter Property="Foreground"
                                    Value="Gray" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style  TargetType="{x:Type ListBoxItem}"
            BasedOn="{StaticResource Style2}">
        <Setter Property="SnapsToDevicePixels"
                Value="true" />
        <Style.Triggers>

            <Trigger Property="ListBox.AlternationIndex"
                     Value="0">
                <Setter Property="Background"
                        Value="CornflowerBlue" />
                <Setter Property="Foreground"
                        Value="Black" />
            </Trigger>

            <Trigger Property="ItemsControl.AlternationIndex"
                     Value="1">
                <Setter Property="Background"
                        Value="LightBlue" />
                <Setter Property="Foreground"
                        Value="Red" />
            </Trigger>
        </Style.Triggers>
    </Style>

好的,我修复了,现在我该如何在ListBox选项中编写它(请参见<Grid>.....)?因为现在只有第一种样式起作用(交替计数不起作用)。 - LTU
检查新更新。:D 好的,您必须知道使用“BasedOn”,新样式将覆盖所有已定义的样式。例如,“Alternation”不能同时工作。只会考虑其中一个,因为该触发器在两种样式中都被定义。 - Shmwel
我该如何让它们一起工作?也许可以将计数属性放在第一个样式中进行交替? - LTU
嗯...我不太明白你想如何将它们组合起来。有没有任何属性取决于它们?至少,要么是这样(例如蓝色和红色),否则就是其他的东西...你能详细解释一下情景吗?正如我所说的,如果两种风格都定义了,那么你不能将它们组合在一起。在同一时间只能应用1个交替触发器(不能是两个、三个等)。 - Shmwel
也许你知道如何制作不需要触发器的交替? - LTU
检查新更新。嗯...这很奇怪。你不应该同时使用两种“做”某些相同的事情的样式。你应该遇到的问题是有两种不同的样式试图修改ListBoxItem背景颜色,这将导致“不能按照你想要的方式重现流程”。 - Shmwel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接