Цвет элемента списка WPF в соответствии со свойством
У меня есть наблюдаемая коллекция объектов Песни. У этих объектов песни есть свойство "Playing", которое является "bool" (я знаю, плохое наименование). Песни отображаются в ListBox в моем приложении. Я хочу, чтобы песня "Воспроизведение" была красного цвета. Я работал с триггерами весь день, пытаясь сделать эту работу. До сих пор я дошел до того, что они окрашены в зависимости от того, на что настроено воспроизведение, когда песня добавляется в список. Можно ли изменить его при изменении свойства Playing? Вот мой 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 ответа
Ваш объект со свойством Playing реализует INotifyPropertyChanged? Если это так, то ваш пользовательский интерфейс должен автоматически обновляться в соответствии с подходом DataTrigger, который вы используете.
Другой подход заключается в использовании ViewModels вместо триггеров (легче понять и работать с ними - когда дела идут не так, как ожидалось). Пример
Обновление: только что посмотрел ваши фрагменты кода. Я обнаружил одну вещь - вам нужно вызвать событие после того, как вы применили новое значение.
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}">
Я в основном изменил фрагмент из примера, который я разместил, чтобы использовать класс вашей песни, а затем изменил нажатие кнопки для переключения между 2 цветами. (Также превратил 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;
}
Мои списки меняют цвет при каждом клике!:)
Чтобы вернуть его обратно, вам также не нужно было бы использовать триггер для 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"
в любой цвет вам нужно.