基于属性为WPF ListBox项着色

时间:2011-05-31 02:54:07

标签: wpf colors triggers listbox listboxitem

我有一个可观察的Song对象集合。这些歌曲对象有一个名为“播放”的属性,这是一个bool(错误的命名,我知道)。歌曲显示在我的应用程序的ListBox中。我希望播放的歌曲是红色的。我一直在尝试使用触发器来完成这项工作。到目前为止,我已经达到了这样的程度,即根据歌曲添加到列表时设置的播放次数对它们进行着色。 Play属性发生变化时是否可以更改? 这是我的XAML:

<Window x:Class="MusicPlayer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MusicPlayer="clr-namespace:MusicPlayer" Title="Music" Height="350" Width="525" Name="Main">
    <Grid>
        <ListBox HorizontalAlignment="Stretch"  Name="Playlist" VerticalAlignment="Stretch" Margin="0,23,0,79" MouseDoubleClick="Playlist_MouseDoubleClick">
            <ListBox.Resources>
                <Style TargetType="ListBoxItem">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=Playing}" Value="True">
                            <Setter Property="Background" Value="Red" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
                <DataTemplate DataType="{x:Type MusicPlayer:Song}">
                    <TextBlock Text="{Binding Path=Title}"/>
                </DataTemplate>
            </ListBox.Resources>

        </ListBox>
        <Button Content="Play" Height="23" HorizontalAlignment="Center" Margin="0,0,330,20" Name="PlayButton" VerticalAlignment="Bottom" Width="75" Click="PlayButton_Click" />
        <Button Content="Stop" Height="23" HorizontalAlignment="Center" Margin="0,0,165,20" Name="stopButton" VerticalAlignment="Bottom" Width="75" Click="stopButton_Click" />
        <Button Content="Next" Height="23" HorizontalAlignment="Center" Margin="165,0,0,20" Name="nextButton" VerticalAlignment="Bottom" Width="75" Click="nextButton_Click" />
        <Button Content="Add Songs..." Height="23" HorizontalAlignment="Center" Margin="330,0,0,20" Name="AddButton" VerticalAlignment="Bottom" Width="75" Click="AddButton_Click" />
        <Button Content="Previous" Height="23" HorizontalAlignment="Center" Margin="0,0,0,20" Name="PreviousButton" VerticalAlignment="Bottom" Width="75" Click="PreviousButton_Click" />
        <Button Content="Pause" Height="23" HorizontalAlignment="Center" Margin="0,0,330,20" Name="PauseButton" VerticalAlignment="Bottom" Width="75" Visibility="Hidden" Click="PauseButton_Click" />
        <Menu Height="23" HorizontalAlignment="Stretch" Name="menu1" VerticalAlignment="Top">
            <MenuItem Header="File">
                <MenuItem Header="Quit" Click="MenuItem_Click" />
            </MenuItem>
        </Menu>
            <Slider Height="23" HorizontalAlignment="Stretch" Margin="10,0,10,50" Name="ProgressBar" VerticalAlignment="Bottom" />
    </Grid>
</Window>

编辑:

实施INotifyPropertyChanged后,使用上方或下方的XAML颜色将变为红色。现在,它不会使用任何一种方法改回白色。我也有一个问题,我的Play方法不会将背景颜色更改为红色,但我的下一个方法将。这是我的代码:http://pastebin.com/EMTUpTin http://pastebin.com/LuK78zGp 这是我的新XAML:

<Window x:Class="MusicPlayer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MusicPlayer="clr-namespace:MusicPlayer" Title="Music" Height="350" Width="525" Name="Main">
    <Grid>
        <ListBox HorizontalAlignment="Stretch"  Name="Playlist" VerticalAlignment="Stretch" Margin="0,23,0,79" MouseDoubleClick="Playlist_MouseDoubleClick">
            <ListBox.Resources>
                <DataTemplate DataType="{x:Type MusicPlayer:Song}">
                    <TextBlock Text="{Binding Path=Title}">
                        <TextBlock.Background>
                            <SolidColorBrush Color="{Binding BackgroundColor}"/>
                        </TextBlock.Background>
                    </TextBlock>
                </DataTemplate>
            </ListBox.Resources>
        </ListBox>
        <Button Content="Play" Height="23" HorizontalAlignment="Center" Margin="0,0,330,20" Name="PlayButton" VerticalAlignment="Bottom" Width="75" Click="PlayButton_Click" />
        <Button Content="Stop" Height="23" HorizontalAlignment="Center" Margin="0,0,165,20" Name="stopButton" VerticalAlignment="Bottom" Width="75" Click="stopButton_Click" />
        <Button Content="Next" Height="23" HorizontalAlignment="Center" Margin="165,0,0,20" Name="nextButton" VerticalAlignment="Bottom" Width="75" Click="nextButton_Click" />
        <Button Content="Add Songs..." Height="23" HorizontalAlignment="Center" Margin="330,0,0,20" Name="AddButton" VerticalAlignment="Bottom" Width="75" Click="AddButton_Click" />
        <Button Content="Previous" Height="23" HorizontalAlignment="Center" Margin="0,0,0,20" Name="PreviousButton" VerticalAlignment="Bottom" Width="75" Click="PreviousButton_Click" />
        <Button Content="Pause" Height="23" HorizontalAlignment="Center" Margin="0,0,330,20" Name="PauseButton" VerticalAlignment="Bottom" Width="75" Visibility="Hidden" Click="PauseButton_Click" />
        <Menu Height="23" HorizontalAlignment="Stretch" Name="menu1" VerticalAlignment="Top">
            <MenuItem Header="File">
                <MenuItem Header="Quit" Click="MenuItem_Click" />
            </MenuItem>
        </Menu>
        <Slider Height="23" HorizontalAlignment="Stretch" Margin="10,0,10,50" Name="ProgressBar" VerticalAlignment="Bottom" />
    </Grid>
</Window>

编辑2: 我刚注意到我有另一个问题。如果我突出显示其中一个带有白色背景的项目,则该文本是不可见的。我该如何解决这个问题? 编辑3: 通过将背景设置为Colors.Transparent而不是Colors.White来解决此问题。

2 个答案:

答案 0 :(得分:4)

为了让它改回来,你是否还必须实现Playing为假时的触发器?像这样:

<ListBox HorizontalAlignment="Stretch"  Name="Playlist" VerticalAlignment="Stretch" Margin="0,23,0,79" MouseDoubleClick="Playlist_MouseDoubleClick">
        <ListBox.Resources>
            <Style TargetType="ListBoxItem">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Playing}" Value="True">
                        <Setter Property="Background" Value="Red" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=Playing}" Value="False">
                        <Setter Property="Background" Value="White" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
            <DataTemplate DataType="{x:Type MusicPlayer:Song}">
                <TextBlock Text="{Binding Path=Title}"/>
            </DataTemplate>
        </ListBox.Resources>

这对我来说似乎是最简单的解决方案。当然,您可以将Value="White"更改为您需要的任何颜色。

答案 1 :(得分:2)

您的Play属性对象是否实现了INotifyPropertyChanged?如果是,那么您的UI应该根据您正在使用的DataTrigger方法自动更新。

另一种方法是使用ViewModels而不是触发器(更容易理解和使用 - 当事情没有按预期进行时)An example

更新: 只是看看你的代码片段。我找到的一件事 - 您需要在之后触发事件,您已经应用了新值。

public Color BackgroundColor
        {
            get { return _backgroundColor; }

            set
            {
                _backgroundColor = value;
                NotifyPropertyChanged("BackgroundColor"); // must be after so that new value is readable by the GUI
            }
        }

此外,dataTemplate必须应用于列表框的ItemTemplate属性

<ListBox.ItemTemplate> <!-- not Resources property -->
                <DataTemplate DataType="{x:Type MusicPlayer:Song}">

我基本上改变了我发布的示例中使用您的歌曲类的片段,然后修改了按钮单击以在两种颜色之间切换。 (还将ListView转换为ListBox)

private bool _isGreen = false;
        private void Button_Click(object sender, RoutedEventArgs e)
        {

            foreach (var item in Items)
                item.BackgroundColor = (_isGreen ? Colors.Cyan : Colors.PaleGreen );
            _isGreen = !_isGreen;
        }

我的列表框会在每次点击时改变颜色! :)